Search code examples
c#json.netjsonpath

SelectTokens with specific c#


In the process I do using the 'Where' method below, I reach the list named 'list1' in the json. I need to do the same operation without using the 'Where' method, only using 'SelectTokens' once.

When I try this(test2) I am only accessing the last item.

var test = jsonVal.SelectTokens("data.list1[*]").Where(x => x.SelectTokens("list2[?(@.value > 15)]").Count() != 0);

var test2 = jsonVal.SelectTokens($"data.list1[*].list2[?(@.value > 15)]");  

ex json:

{
    "data": {
        "list1": [
            {
                "list2": [
                    {
                        "value": 20
                    }
                ]
            },
            {
                "list2": [
                    {
                        "value": 10
                    }
                ]
            }
        ]
    }
}

Note: JSON can be confusing. Basically what I want is to be able to pass a specific part of my query into a variable.

Demo fiddle here.


Solution

  • You can use nested filter expressions to select all entries of list1 that have at least one matching entry of list2 like so:

    var items = jsonVal.SelectTokens("data.list1[?(@.list2[?(@.value > 15)])]");        
    

    The returned items, when serialized, match the contents of test as required:

    [
      {
        "list2": [
          {
            "value": 20
          }
        ]
      }
    ]
    

    Notes:

    • The inner expression list2[?(@.value > 15)] selects all entries of list2 with value > 15.

    • The outer expression data.list1[?(@list2 query)] selects all entries in list1 that have matching entries in list2.

    • I'm not sure that nested filter expressions work on all JSONPath implementations. If I try the above query + JSON on https://jsonpath.curiousconcept.com/, neither Stefan Goessner's JSONPath 0.8.3 nor Flow Communications's JSONPath 0.5.0 can evaluate the query.

      The JSONPath proposal merely states that ?() should applies a filter (script) expression "using the underlying script engine" which is quite ambiguous.

    Demo fiddle here.