Add string literal into JSONPath output - json

Can I add a string literal to a JSONPath selector?
{ "items": [
{ "x": 1 },
{ "x": 2 },
{ "x": 3 },
{ "x": 4 }]
}
$.items[:].x gives...
[
1,
2,
3,
4
]
For example, can I make it return...
[
{ 1 },
{ 2 },
{ 3 },
{ 4 }
]
I want to generate some code that adds items to a dictionary.

As discussed in the comments, this cannot be done using JSONPath (alone) since a path query returns only valid JSON and the target format is not valid. In general, JSONPath is not the right tool here, a JSON transformation using a library like Jolt would be more appropriate; but again, similar to XSLT transformations, we can only create valid output. So, as you already have found out, you would need to use string functions to mingle the code as needed. For instance, a regex substitution could do:
const regex = /(\d+),?/gm;
const str = `[
1,
2,
3,
4
]`;
const subst = `{ $1 },`;
// The substituted value will be contained in the result variable
const result = str.replace(regex, subst);
console.log('Substitution result: ', result);

Related

Output json stringify elements

I have a problem. I am using TypeScript and I get a response back. I want to output the information. How could I output e.g. internalCompanyCode and timestamp.
What I got
Element implicitly has an 'any' type because index expression is not of type 'number'.(
//const json = JSON.stringify(result, null, 2)
// json is the result of JSON.stringify(...)
const json = [
{
"internalCompanyCode": "007",
"moreInfo": [
{
"dimensions": {
"height": 27,
"width": 31,
"length": 61
},
"currenStatus": {
"arrived": {
"timestamp": "10:00:12"
}
}
}
]
}
]
console.log(json['internalCompanyCode'])
console.log(json['moreInfo']['dimensions']['height'])
To get data you don't have to stringify result. You have to use result before stringifying to json or have to parse json back to result if you did it
console.log(result[0]['internalCompanyCode']) //007
console.log(result[0]['moreInfo'][0]['currenStatus']['arrived']['timestamp']) // 10:00:12
console.log(result[0]['moreInfo'][0]['dimensions']['height']) //27
Your json object is actually a list so you will have to access it like json[0]['internalCompanyCode']

Manipulating nested array of obects in RedisJSON

I have a JSON with nested array like below to be saved in Redis. I am using RedisJSON module to save the data as JSON.
customer:12345 : {
info : {
key1: val1,
key2: val2,
key3: val3
},
rides: [
{
rideid: xxx,
from: fromval,
to: toval,
date: dateofride,
distance: distanceval,
points: pointsval
},
{
rideid: yyy,
from: fromval,
to: toval,
date: dateofride,
distance: distanceval,
points: pointsval
},
...
]
}
I have a case where a new item can be added to the array or the existing one can be edited. I am using node-redis client with express.js. Express app receives only the data which is changed or added in rides array. If the item is already in the array, new data has to replace the existing array item (rideid is the key of each object), else it has to be added to the array. How do I achieve this?
Given the following JSON document
{
"info": {
"key1": "val1"
},
"rides": [{
"rideid": "xxx",
"points": 0
},
{
"rideid": "yyy",
"points": 10
}
]
}
Which is held by the key customer:12345 in RedisJSON with the following command
127.0.0.1:6379> JSON.SET customer:12345 . "{\"info\": {\"key1\": \"val1\",\"key2\": \"val2\",\"key3\": \"val3\"},\"rides\":[{\"rideid\": \"xxx\",\"points\": 0 },\t{\"rideid\": \"yyy\",\"points\": 10}]}"
You can update ride with rideid yyy by e.g. incrementing the score by 5 as follows
127.0.0.1:6379> JSON.NUMINCRBY customer:12345 "$.rides[?(#.rideid=='yyy')].points" 5
"[15]"
$.rides[?(#.rideid=='yyy')].points is a JSONPath expression (more here and here and also answered here)
To add a new ride
127.0.0.1:6379> JSON.ARRAPPEND customer:12345 $.rides "{\"rideid\": \"zzz\",\"points\": 5 }"
1) (integer) 3
All RedisJSON commands can be found here

How to parse JSON data with custom object names?

I want to parse a JSON with Typescript, where object names can vary and I have no way to know them all. For example:
{
"planets": {
"Alderaan": {
"available_items": {
"Cinamone": {
"available": 74,
"buy_price": 6,
"sell_price": 6
},
"Dwimeryt": {
"available": 42,
"buy_price": 12,
"sell_price": 11
}
}
}
}
Where there can be many planets with different names.
I figured out that in order to parse JSON object successfully, we need to have corrent variable names, so for example that works:
interface MyObj {
x: number;
y: number:
}
let json_string = `{
"x": 5,
"y": 12
}`;
let test: MyObj = JSON.parse(json_string);
But if we change variable name in interface from "x" to lets say "xx" it becomes undefined after parsing. That creates seemingly unsolvable problem if we cant know all of the JSON object names, because I cant create an interface withh all of the planet names. Am I missing something? How would you parse a JSON I have posted?
Do you have any influence on the JSON itself? To me it seems that it is not the best way to use JSON. If I would try to design this, your JSON would look more like this:
{
"planets": [
{
"name": "Alderaan",
"available_items": [
{
"name": "Cinamone",
"available": 74,
"buy_price": 6,
"sell_price": 6
}, {
"name": "Dwimeryt",
"available": 42,
"buy_price": 12,
"sell_price": 11
}]
}]
}
This way you would always know the name of the fields and also their types. I do not think that this could be achieved easily with the current JSON format.

Combine two objects using JsonPath

Suppose I have json like this:
[
{
"a": 1,
"b": 2,
"c": 3,
},
{
"a": 1,
"b": 2,
"d": 4
}
]
Is it possible to write a JsonPath which will give me:
{
"a": 1,
"b": 2,
"c": 3,
"d": 4
}
The order of the elements in the list is not sure, however the element names I know beforehand. So I thought I could use JsonPath to select all elements with names 'a', 'b', 'c' or 'd' and put them in a single object. However, I now have tried several things and I start to doubt whether what I want is possible.
For example I can select an object which has an element c with:
$[?(#.c)]
And I can also select just the value of d with something like:
$..d
But I can not find any way to comebine them into a single object. Is what I want possible with JsonPath or is this a limitation of JsonPath?
I think the appropriate way to do this is to remove the second object and apply the difference between them to the first one:
[
{ "op": "remove", "path": "/1" },
{ "op": "add", "path": "/0/d", "value": 4 }
]
Assuming you're OK with polyfilling for IE (it's ES6), use Object.assign:
const object1 = {
a: 1,
b: 2,
c: 3
};
const object2 = {
d: 4
}
const objectMerged = Object.assign({}, object1, object2);
console.log(objectMerged.c);
console.log(objectMerged.d);
For full details, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Browser_compatibility

Add up numerical values of entry in json and store in variable as string

I have a JSON file that is being generated from an API and stored into a variable myJson that looks like this:
{
"results": [
{
"term": "A",
"count": 1569
},
{
"term": "B",
"count": 1375
},
{
"term": "C",
"count": 1372
}
]
}
Is there any approach to add up all of the numerical values in the "count" entry and store it as a string into a variable?
So: stringVariable = 1569 + 1375 + 1372
Note: This is just a small snippet of a giant JSON file so I believe will need a formula of some sort.
Thanks!!
Without knowing what language you're asking about, let's use JavaScript.
function add(data) {
let sum = 0;
data['results'].slice(1).forEach( obj =>
sum += obj['count']
);
return sum;
}