I have a JSON like this one:
{
"options": [
{
"price": 217,
"quantity": 2
},
{
"price": 63,
"quantity": 5
}
]
}
And I want to query it with JsonPath to get the product of "price" and "quantity" for every element in the "options" array.
I use this site to play around with the syntax. And I actually found a way to do it:
options[?(@.result = @.price * @.quantity)].result
This syntax adds a property ‘result’ to each element and stores the product in it like that:
[
{
"price": 217,
"quantity": 2,
"result": 434 // yay!
},
{
"price": 63,
"quantity": 5,
"result": 315 // yay!
}
]
So the final result is exactly what I want:
[
434,
315
]
I don’t really need to set any properties. I just want the result like that.
The problem is – it doesn’t work in the C# application (with Newtonsoft.Json). It can’t parse the query.
I tried to introduce the property in JSON beforehand, it didn’t work either.
json = JObject.Parse(@"{}"); // same JSON as above
var result = json.SelectTokens("options[?(@.result = @.price * @.quantity)].result"); // exception
Could you please help me to figure it out?
Note: I only have UI at my disposal. No access to code, no LINQ, no API calls. I just happened to know the underlying implementation.
2
Answers
JSONPath syntax was not that well standardized for quite some time. So one implementation and what it does support can vastly differ from another (in particular the online tool which you have tried – I found it far more lax than JSONPath implementations I worked with). For example this site which I usually use as reference for the syntax seems to be missing the options you have tried. And this online validator does not process this query expression as you expect.
Note that as stated in the
JToken.SelectToken
Method doc:So it arguably should not support such syntax at all. And based on the tests in the Newtonsoft.Json github repo such syntax is not tested (at least in tests I have looked through) and it is safe to assume that it is not supported.
So I suggest to just iterate elements of the array and calculate needed value:
Also note that there is pending IETF specification and according to it JSONPath is query-only and does not support such syntax.
JSON Path is a query-only syntax. It can only return values that are already in the JSON document; temp vars and other such things are not supported (though I like the idea).
There is a pending specification (just waiting on IETF to issue an RFC number): https://www.ietf.org/archive/id/draft-ietf-jsonpath-base-21.html. Once that’s official, I expect many implementations will move to support it. For now, in .NET, only my JsonPath.Net implements the spec.
There are a number of issues in the Github repo where we’re managing the spec that we’re considering for a "v2". I expect this assignment / creation of temp vars thing would be a good one if you’d like to add it.