Open SpikeBlues opened 7 years ago
Works fine for me, though your jsonpath has some errors. Change author to authors and just use just the last name in your jsonpath.
This one $.store.book[?(@.authors[?(@.lastName == 'Waugh')])]
returns expected result.
Hi @tjakopanec Thanks for pointing it out. I have fixed my typo. However, I don't see it working as my expectation. The filter does not work as it will return everything including those books whose authors' name were not "Waugh". Would you give it a try?
I've just tried it again and it works as I expect it to run. Just to avoid any confusion, this is my input:
{ "store": { "book": [ { "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95 }, { "category": "fiction", "authors": [ { "firstName": "Nigel", "lastName": "Rees" }, { "firstName": "Evelyn", "lastName": "Waugh" } ], "title": "Sword of Honour", "price": 12.99 }, { "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "price": 8.99 }, { "category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", "isbn": "0-395-19395-8", "price": 22.99 } ], "bicycle": { "color": "red", "price": 19.95 } }, "expensive": 10 }
This is the jsonPath I use: $.store.book[?(@.authors[?(@.lastName == 'Waugh')])]
This is the result I'm getting: [ { "category" : "fiction", "authors" : [ { "firstName" : "Nigel", "lastName" : "Rees" }, { "firstName" : "Evelyn", "lastName" : "Waugh" } ], "title" : "Sword of Honour", "price" : 12.99 } ]
Is this the result you would expect?
Hi @tjakopanec thanks for the updates.
It works with your particular Json input, as the second element in the book
array is the only one with a 'complicated' author object. However in my case if all books have a child arraynode authors
, the filtering logics does not work as intended. Would you please have a look at my example as follows?
"store": {
"book": [
{
"category": "reference",
"authors": [
{
"firstName": "Nigel",
"lastName": "Rees"
},
{
"firstName": "Evelyn",
"lastName": "Waugh"
}
],
"title": "Sayings of the Century",
"price": 8.95
},
{
"category": "fiction",
"authors": [
{
"firstName": "A",
"lastName": "B"
},
{
"firstName": "C",
"lastName": "D"
}
],
"title": "Sword of Honour",
"price": 12.99
},
{
"category": "fiction",
"authors": [
{
"firstName": "A",
"lastName": "D"
},
{
"firstName": "Evelyn",
"lastName": "X"
}
],
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{
"category": "fiction",
"authors": [
{
"firstName": "Nigel",
"lastName": "Rees"
},
{
"firstName": "Evelyn",
"lastName": "X"
}
],
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
},
"expensive": 10
}
The JsonPath I am using is the same as yours: $.store.book[?(@.authors[?(@.lastName == 'Waugh')])]
Thank you.
Sorry for the late reply. Yeah, you are right. I've tried it on some of my examples and it's not working correctly.
I guess the author of the library should have a look then.
+1 Seeing the same issue. This is stopping us us writing any jsonpath queries containing nested filters.
Any update on how to fetch parent when filter is applied on child node
Hi, has there been any update on this issue? If not Jayway's, do any other Jsonpath implementations support this feature (grabbing the parent based on a predicate on a child)?
Really looking forward to have this issue resolved for the Jayway implementation.
This functionality is needed in our project. Any updates?
really needed feature to extract parent data from filtering nested arrays
+1
+1
+1
+1
+1
+1
+1
just found a workaround, now I am using the library "jsonpath-plus": "^0.16.0"
and I am able to search and go back to the parent node using the expression: $..[?(@.firstName=="A")]^title
+1
Project appears to be dormant...
+1
+1
+1
+1
+1
This works for me if authors was a map and not a list $.store.book[?('Waugh' == @['authors']['lastName'])]
. This works as well $.store.book[?('Waugh' == @['authors'][1]['lastName'])]
but it doesn't seem to like using wildcard in expressions
$.store[?(@.friends[?(@.name == 'Shawn Holman')])]
I hope to it will works fine.
Is there any any update on this one, this would be really helpful.
I found this works as expected with Json.Net, at least with version 12.0.3
My query $.purchases[?(@.payments[?(@.type == 'CASH')])]
I can't post the data here without a lot of heavy editing but the query is the same nested array query to return the parent purchase objects where there is a payment with type CASH.
Having same issue but perhaps this behaviour is as per jsonpath spec. If authors is an array, the parent node of a filter for, say, lastname=="Waugh"
is simply the authors array (and not the book object to which the array belongs).
The jsonpath-plus
module behaves the same. So, we either need support for nested filters or an option to get the parent of the parent (i.e. the parent of the array which will be the book object I'm looking for), or to ignore/skip arrays when getting the parent.
Currently, to get the desired result, I have to first do a paths
request and then a value
request using the object index extracted from the paths
result. So, two jsonpath evaluations to find a book (or books) that have an author with a lastname of "Waugh".
As a workaround (it works on https://jsonpath.herokuapp.com/ but not other simulators):
JsonPath : $.[?(@.c[*].d contains "d3" )]['a', 'b']
Input : [ { "a": "a1", "b": "b1", "c": [ { "d": "d1", "e": "e1" }, { "d": "d2", "e": "e2" } ] }, { "a": "a2", "b": "b2", "c": [ { "d": "d3", "e": "e3" } ] } ]
It brings the correct result :
[ { "a" : "a2", "b" : "b2" } ]
Building off of the previous answer from ArtVandalayy - using the modified book store example input (with authors as a complex object):
{
"store": {
"book": [
{
"category": "reference",
"authors": [
{
"firstName": "Nigel",
"lastName": "Rees"
},
{
"firstName": "Evelyn",
"lastName": "Waugh"
}
],
"title": "Sayings of the Century",
"price": 8.95
},
{
"category": "fiction",
"authors": [
{
"firstName": "Herman",
"lastName": "Melville"
},
{
"firstName": "Somebody",
"lastName": "Else"
}
],
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{
"category": "fiction",
"authors": [
{
"firstName": "Evelyn",
"lastName": "Waugh"
},
{
"firstName": "Nigel",
"lastName": "Rees"
}
],
"title": "Sword of Honour",
"price": 12.99
},
{
"category": "fiction",
"authors": [
{
"firstName": "J. R. R.",
"lastName": "Tolkien"
}
],
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
},
"expensive": 10
}
Using this path, which filters on authors with last name given:
$.store.book[?(@.authors..lastName contains "Waugh")].title
Or alternate path if deepscan operator '..' is not supported:
$.store.book[?(@.authors[*].lastName contains "Waugh")].title
We get this correct output according to https://jsonpath.herokuapp.com/ ver 2.3.0 - 2017-07-04 14:54:00
[
"Sayings of the Century",
"Sword of Honour"
]
Hello Everyone,
I have a similar requirement.
{ "store" : { "10162021" : { "id" : 812340, "properties" : { "server" : "server1.example.org", "serverip" : "", } }, "10162022" : { "properties" : { "serverip" : "127.0.0.1", "server" : "server2.example.org", }, "id" : 8890890 } } }
where I need the value of the entries right under sore like these values "10162022" "10162021" from above code.
appreciate any suggestions.
It's may not be a bug. @ArtVandalayy makes a good point. As stated in documentation, filter expression must evaluate to a boolean value.
The problem with previous solution $.store.book[?(@.authors[?(@.lastName == 'Waugh')])]
is;
?(@.lastName == 'Waugh')
evaluates to a boolean, which is OK,?(@.authors[XX])
emits an object. So we can assume that, $.store.book[?(@.authors[*])]
produces the same result as expression $.store.book[?(@.authors[?(@.lastName == 'Waugh')])]
when there is at least one author with lastName 'Waugh'. @ArtVandalayy's solution converts main expression to the boolean;
$.[?(@.c[*].d contains "d3" )]['a', 'b']
If we convert it for the example, it will be something like
$.store.book[?(@.authors[?(@.lastName == 'Waugh')].lastName contains 'Waugh')]
Yeah, it works, but there are other options.
We can check for an empty.
$.store.book[?(@.authors[?(@.lastName == 'Waugh')] empty false)]
When filter expression checks for an empty false
, then result contains only the books with an author that last name is 'Waugh'. When empty true
, the result will become the inverted version of the first one. The books of authors with lastName 'Waugh' will become excluded from the list.
And, there are more filter operators to use: https://github.com/json-path/JsonPath#filter-operators
@tolpp, @dengmingcong, @thadguidry, @VerkhovtsovPavel
I tried
$.store.book[?(@.authors[?(@.lastName == 'Waugh')] empty false)]
and
$.store.book[?(@.authors[?(@.lastName == 'Waugh')].lastName contains 'Waugh')]
with jsonPath.Com and newtonsoft 13.0.3.
It does not work.
JsonPath fails as - "jsonPath: Unexpected token '?': _$v.authors[?($_v.lastName == 'Waugh'"
NewtonSoft fails as - "'Could not read query operator.'"
Am I missing anything?
I tried
$.store.book[?(@.authors[?(@.lastName == 'Waugh')] empty false)]
and$.store.book[?(@.authors[?(@.lastName == 'Waugh')].lastName contains 'Waugh')]
with jsonPath.Com and newtonsoft 13.0.3.It does not work.
JsonPath fails as - "jsonPath: Unexpected token '?': _$v.authors[?($_v.lastName == 'Waugh'"
NewtonSoft fails as - "'Could not read query operator.'"
Am I missing anything?
I think jsonpath[.]com is based on different JsonPath implementation.(https://github.com/ashphy/jsonpath-online-evaluator)
It still works on https[:/]/www.javainuse[.]com/jsonpath
@raviraj-bhalerao
@tolpp That was very quick ans. And thank you very much. True it works with javainuse.
Would you have any idea where I can see how nested queries can be written for newtonsoft or how this query should be changed to get same results in newtonsoft please?
I wonder if it is possible to filter on the child level complex objects (not simple string), and retrieve those parent nodes whose children matches the predicts.
Taking the bookstore example from Jayway's github project: https://github.com/jayway/JsonPath#path-examples.
If I would change "author" to a more complex object like following:
With that, how can I get back "all books that were written by someone with last name of 'Waugh' " ?
I have tried with Json Evaluator (http://jsonpath.herokuapp.com/) to use something like
$.store.book[?(@.authors[?(@.lastName == 'Waugh')])]
, but it seems like the filter doesn't work. I am guessing Jayway does not allow a nested predicates. If that's the case, would there be any workaround for this?