I looked at another qs. But the ans does not work with newtonsoft 13.0.3.
I have posted my qs on github.
Basically in a json like
{
"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
}
I would like to get the jsonpath filter expression that would allow me select title of the book with an author whose last name is Waugh. I am using Newtonsoft 13.0.3 with C#.
Nested queries are supported by SelectTokens()
but the empty false
syntax from the linked answer is not. Instead use the ?(<boolean expr>)
syntax as shown in the original JSONPath proposal to select array members that have matching properties like so:
var titles = jtokenRoot
.SelectTokens("store.book[?(@.authors[?(@.lastName == 'Waugh')])].title")
.ToList();
Demo fiddle #1 here.
Notes:
authors[?(@.lastName == 'Waugh')]
selects any author that has a lastName
of Waugh
.
store.book[?(@.authors[?(@.lastName == 'Waugh')])]
selects any book that has any author that has a lastName
of Waugh
.
See this answer to SelectTokens with specific c# for another example of a nested query.
The original JSONPath proposal states that ()
should be a script expression, using the underlying script engine -- but does not specify any requirements for that "underlying script engine" in any way, which clearly leaves some room for interpretation as to what queries should and should not be supported. Thus, while most JSONPath query engines support the simple examples shown in the proposal, they all seem to differ on what is supported beyond that.
Newtonsoft has its own query engine, the code for which can be found here.
For more complicated string matching, you can use Newtonsoft's regex operator =~
. For instance, the following query strips leading and trailing whitespace and ignores case:
SelectTokens("store.book[?(@.authors[?(@.lastName =~ /^(?i)[\\s]*waugh[\\s]*$/)])].title")
Hat tip to this answer by stevemegson to C# RegEx: Ignore case... in pattern? for the (?i)
syntax.
Demo fiddle #2 here.