jsonpathjson-everything

JSONPath "$[length(@.foo)]" fails to return array length when tested via json-everything library


This seems like a simple use case. We are trying to obtain the number of items in an array using the JSONPath function length().

The test object is:

{
   "array": [1,2,3]
}

The JSONPath that were tested include:

$[length(@.foo)]

and

$.foo.length()

In both cases, the result via the json-everything library test page is "Path is invalid":

We are currently using the Newtonsoft.Json library which does not seem to support JSONPath aggregate or filtering functions.

We were encouraged to try the json-everything library thank to this comment on GitHub which claims that length() is supported.

The json-everything release notes shows that this function should be supported as of version 0.30.

Thanks for your help.


Solution

  • According to the spec, all functions (including length()) are only valid inside filter expressions. There are some issues (that will be further discussed if a JSON Path 2.0 is ever developed) that discuss using a function outside of filter expressions, but that didn't make it into the spec's first release.

    Because of that, expressions like $[length(@.foo)] and $.foo.length() are invalid.

    A valid use of the length() function is something like $.foo[?length(@) > 5], which would find all children of foo which themselves have more than 5 children.

    Extending your example,

    {
       "array": [1,2,3],
       "obj": { "foo": 1, "bar": 2, "baz": 3 },
       "longer": [1,2,3,4,5],
       "not-array": 3
    }
    

    the path $[?length(@) == 3] would select the nodes at $.array and $.obj because their values are containers with 3 items, but it wouldn't select $.longer or $.not-array because their values aren't containers with 3 items.

    My suggestion for $[length(@.foo)] is to use a negative index: $[-1], and for $.foo.length(), use $.foo and just count the results in code.