JSONPath exclude as separate JSON - javascript

I have a complex JSON Structure . I wan't to exclude a part and get the list in two buckets. Say One as "inclusions" and another as "exclusions".
Sample JSON is given below.
{
"Item": {
"Items": [{
"Items": [{
"category": "fruit",
"Item": {
"Items": [{
"Text": "Apple"
},
{
"Text": "Orange"
},
{
"Text": "Grapes"
},
{
"Text": "Guava"
}],
"Types": ["Value",
"Value",
"Value",
"Value"]
},
"Type": "Or"
},
{
"category": "fruit",
"Item": {
"Text": "Pineapple"
},
"Type": "Value"
}],
"Types": ["Constraint",
"Constraint"]
},
{
"category": "fruit",
"Item": {
"Text": "Banana"
},
"Type": "Value"
}],
"Types": ["Not",
"Constraint"]
},
"Type": "And"}
Here we have category fruits where We Apple,Orange ,Grapes and Guava are with "OR" and pineapple with "AND" Type and Banana is with "Not" .Once I Try
Item..Items[?(#.category='fruit')]..Text
It returns me
[ "Banana", "Apple", "Orange", "Grapes", "Guava", "Pineapple"]
But I want List to be
{["Apple", "Orange", "Grapes", "Guava", "Pineapple" ]
},{["Banana"]}
Is there a way in JSON Path to get something of similar structure

That may be not the answer you expected, but I don't think that's possible with JsonPath.
Quote from jayway/JsonPath
When evaluating a path you need to understand the concept of when a path is definite. A path is indefinite if it contains:
.. - a deep scan operator
?() - an expression
[, (, )] - multiple array indexes
Indefinite paths always returns a list (as represented by current JsonProvider).
So your result will always be a list. What you already have is the closest you can get, I think.

That can not be done using JSONPath.

Related

Filter array of specific objects

How to use filter or forEach in javascript to output only the objects whithout parentId and the objects with only the first level of parentId.
Should output objects with ids: 1681, 1682, and 1683.
Should not output objects with ids: 1685, 1686 and 1687.
array = [ {
"id": 1681,
"label": "1",
"url": "page1",
},
{
"id": 1682,
"label": "2",
"url": "page1",
},
{
"id": 1683,
"label": "a",
"url": "page1",
"parentId": 1681,
},
{
"id": 1685,
"label": "aa",
"url": "page1",
"parentId": 1683,
},
{
"id": 1686,
"label": "aaa",
"url": "page1",
"parentId": 1683,
},
{
"id": 1687,
"label": "aaaa",
"url": "page1",
"parentId": 1683,
}
]
Something like this...
array.filter(({item}) => !item.parentId ? item.id : item.parentId)
We have to save the information if we already found a parentId from inside the filter function. A handy way to do this is by using the prefix operator ++ on a counter. This way we get around an explicit, long assignment with =. Instead we make it before.
Additionally with destructuring assignment we can extract the parentId comfortably of the array items and write a really short filter:
array=[{id:1681,label:"1",url:"page1"},{id:1682,label:"2",url:"page1"},{id:1683,label:"a",url:"page1",parentId:1681},{id:1685,label:"aa",url:"page1",parentId:1683},{id:1686,label:"aaa",url:"page1",parentId:1683},{id:1687,label:"aaaa",url:"page1",parentId:1683}];
window.parentIdCount = 0;
window.filtered =
array.filter(({parentId}) => !parentId || ++parentIdCount <= 1)
console.log(filtered)
Something like this ought to work:
const result = array.filter(object => object.parentId === undefined);

Accessing nested array properties

This may be extremely simple but I've not been able to figure out how to iterate over and access the properties in the following mix (I think) of arrays and nested objects:
myFilters = {
"color_Filter": [{
"name": "BLUE",
"count": 1,
"dataId": "BLUE"
},
{
"name": "Black",
"count": 5,
"dataId": "Black"
},
{
"name": "Blue",
"count": 14,
"dataId": "Blue"
}
],
"size_Filter": [{
"name": "10",
"count": 16,
"dataId": "10"
},
{
"name": "12",
"count": 16,
"dataId": "12"
}
]
}
What would the correct looping structure be here to pull out name, count etc from the above? The desired output is to output a string from the above with color_Filter=BLUE,Black,Blue/size_Filter=10,12
I've tried a few different approaches and none of them have been successful so far.
You could map the entries of the object and create a string for each key. Get the name from the value array using map. Then join the array of strings with a /
const myFilters = {color_Filter:[{name:"BLUE",count:1,dataId:"BLUE"},{name:"Black",count:5,dataId:"Black"},{name:"Blue",count:14,dataId:"Blue"}],size_Filter:[{name:"10",count:16,dataId:"10"},{name:"12",count:16,dataId:"12"}]};
const output = Object.entries(myFilters)
.map(([k,arr]) => `${k}=${arr.map(a => a.name)}`)
.join("/")
console.log(output)

Javascript parse JSON data into multiple variables storing separate records in memory

I have used JSON stringify and JSON Parse etc..., but I'm having trouble with finding /figuring how how to split up my JSON result into multiple variables.
Issue: I have a JSON result with 2 to many results (sections, pages etc...)
Goal : To store each result /row into its own variable.
Example of FULL unparsed JSON result:
{
"pages": [
{
"name": "page1",
"elements": [
{
"type": "text",
"name": "question1"
}
]
},
{
"name": "page2",
"elements": [
{
"type": "checkbox",
"name": "question2",
"choices": [
"item1",
"item2",
"item3"
]
}
]
}
]
}
In the example, notice that "name": "page1" and page2 are the clear separators, I could end up having them calling SectionA , SectionB etc.. but that shouldn't be important.
I need to store them separately
I also need to maintain that complete JSON structure
example of what i want to do with it
var page1 =
{
"pages": [
{
"name": "page1",
"elements": [
{
"type": "text",
"name": "question1"
}
]
}
]
}
2nd one:
var page2 =
{
"pages": [
{
"name": "page2",
"elements": [
{
"type": "checkbox",
"name": "question2",
"choices": [
"item1",
"item2",
"item3"
]
}
]
}
]
}
Notice that not only is it broken apart, but the main part I want to have maintained in the variable "pages: [
Just a simple map() operation would do it.
Afterwards you can use array destructuring to capture your result into separate variables:
const data = {
"pages": [{
"name": "page1",
"elements": [{
"type": "text",
"name": "question1"
}]
},
{
"name": "page2",
"elements": [{
"type": "checkbox",
"name": "question2",
"choices": [
"item1",
"item2",
"item3"
]
}]
}
]
};
const split = data.pages.map(p => ({pages: [p]}));
console.log(split);
const [page1, page2] = split;
console.log(page1);
console.log(page2);

Merging two JSONata expressions

I am using JSONata for performing JSON to JSON transformation.
For some unique reasons, I want to merge two JSONata expressions :
As an example :
Parent Expression:
var script = `
{
"data":
{
"name" : data.payload.Name.(FirstName & ' ' & LastName),
"alias": data.payload.Name.(Salutation & ' ' & FirstName),
"active": data.payload.Status = 'New' ? true : false,
"signature": "Have good day ," & data.payload.Name.FirstName & "!"
}
}
`;
Also I have few simple assignment kind of JSONata expression like :
Expression 1 :
{
"source" : source
}
Expression 2 :
{
"data": {
"email" : data.payload.Email
}
}
I would like to add above two expressions to expressions defined using script.
So after adding these two expressions, I should be able to get :
var script = `
{
"source": source,
"data":
{
"name" : data.payload.Name.(FirstName & ' ' & LastName),
"alias": data.payload.Name.(Salutation & ' ' & FirstName),
"active": data.payload.Status = 'New' ? true : false,
"signature": "Have good day ," & data.payload.Name.FirstName & "!",
"email": data.payload.Email
}
}
`;
How do I do using javascript/JSONata ?
Background and constraints :
Child Expressions (expression 1 and 2 in the example) (that is supposed to be added into Parent expression) will always be simple assignment like "a" : x.y.z or "b" : x.
Child Expressions may already be present in parent expression. In that case, it replaces assignment.
Also I want to delete some json paths from parent expression (ofcouse , if it is present) like If delete path data.Email.
What I have done ? :
I tried to convert JSONata script to JSON by putting values under double quotes and encoding value using escape() function.
Once I have JSON, I look for path mentioned in child expression (like data.Email)
If path exists : replace its value
If path does not exist : create path and assign value
If path is supposed to be deleted : simply delete it.
Once I have done processing above JSON,
I convert it to JSONata script by removing quotes using bunch of regex and then applying unescape() method for decoding.
The problem with this approach is :
It is not reliable (regex matching and replacement is not fullproof)
I am not sure whether every JSONata (which does not declare any functions) can be converted to valid JSON always.
I think that your best bet might be to translate your expressions to the JSONata AST and then merge them into a new AST.
Here's a super simple example:
const ast1 = jsonata(expr1).ast();
const ast2 = jsonata(expr1).ast();
if (ast1.type !== "unary" || ast2.type!== "unary") throw Error("Only support unary expressions")
const combinedAst = {
"type": "unary",
"value": "{",
"lhs": [...ast1.lhs, ast2.lhs]
}
// TODO: Serialize the AST or inject it into jsonata()
The problem is what to do with your new AST. In my case I also wrote a custom serializer to turn the AST back into a JSONata string, and evaluate that.
ASTs in use
AST for Expression 1
{
"type": "unary",
"value": "{",
"position": 1,
"lhs": [
[
{
"value": "source",
"type": "string",
"position": 13
},
{
"type": "path",
"steps": [
{
"value": "source",
"type": "name",
"position": 22
}
]
}
]
]
}
AST for Expression 2
{
"type": "unary",
"value": "{",
"position": 1,
"lhs": [
[
{
"value": "data",
"type": "string",
"position": 10
},
{
"type": "unary",
"value": "{",
"position": 13,
"lhs": [
[
{
"value": "email",
"type": "string",
"position": 26
},
{
"type": "path",
"steps": [
{
"value": "data",
"type": "name",
"position": 33
},
{
"value": "payload",
"type": "name",
"position": 41
},
{
"value": "Email",
"type": "name",
"position": 47
}
]
}
]
]
}
]
]
}
Combined AST
{
"type": "unary",
"value": "{",
"position": 1,
"lhs": [
[
{
"value": "source",
"type": "string",
"position": 12
},
{
"type": "path",
"steps": [
{
"value": "source",
"type": "name",
"position": 20
}
]
}
],
[
{
"value": "data",
"type": "string",
"position": 30
},
{
"type": "unary",
"value": "{",
"position": 33,
"lhs": [
[
{
"value": "email",
"type": "string",
"position": 46
},
{
"type": "path",
"steps": [
{
"value": "data",
"type": "name",
"position": 53
},
{
"value": "payload",
"type": "name",
"position": 61
},
{
"value": "Email",
"type": "name",
"position": 67
}
]
}
]
]
}
]
]
}

What is wrong with this JSON file?

I put it in a parser and all it gives me is "expecting string on line 19". I have no idea what that means.
{
"name": "Rajeev",
"children": [
{
"name": "Joe",
"children": [
{
"name": "Kevin",
"children": [
{
"name": "George"
}
]
},
{
"name": "John",
"children": [
{
"name": "Barb",
}{
"name": "Michael",
}{
"name": "Charles"
}
]{
"name": "Ravinder"
]
},
Your commas are in the wrong place, e.g.
"children": [
{
"name": "Barb"
},{
"name": "Michael"
},{
"name": "Charles"
}
]
The left one is the right one. see for yourself. you had many extra , and unclosed { and [
http://i.stack.imgur.com/9yKNN.jpg
You have a property / value:
"name": "Barb",
… with a trailing comma so the next thing must be another property / value (the string mentioned in the error message is the property name).
However you have:
}{
Either remove the comma or add more details about Barb.
Then you will need to put a comma between the two objects:
}, {
It seems likely that you intended to place the comma causing teh error between the two objects, so you can just move them.
(You have similar errors throughout the rest of the file)
Sorry for the first answer, I saw a missing comma and automatically assumed that was it, but there were many other errors in there. I think this is what you're trying to do
[
{
"name": "Rajeev",
"children": [
{
"name": "Joe",
"children": [
{
"name": "Kevin",
"children": [
{
"name": "George"
}
]
},
{
"name": "John",
"children": [
{
"name": "Barb"
},
{
"name": "Michael"
},
{
"name": "Charles"
}
]
}
]
}
]
},
{
"name": "Ravinder"
}
]

Categories