skip to Main Content

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


  1. 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:

    Selects a JToken using a JPath expression. Selects the token that matches the object path.

    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:

    var results = new List<int>();
    foreach (var elem in json["options"])
    {
        results.Add(elem["price"].Value<int>() * elem["quantity"].Value<int>());
    }
    

    Also note that there is pending IETF specification and according to it JSONPath is query-only and does not support such syntax.

    Login or Signup to reply.
  2. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search