0

So I'm working with some token filtering at the moment, and have a situation where I need to filter tokens based on the filter condition in C# using the SelectTokens() method, with the catch that if a single value matches the query, I want all objects and/or the root element, for brevity, this is one of the underlying arrays that I want to apply the filtering to:

[
  {
    "unitPrice": 5
  },
  {
    "unitPrice": 13
  }
]

where for example if a single value is above 10, I would want all of the elements in that array, and otherwise no return value, so if I were to use a query like this: $[?($[?(@.unitPrice >= 10)] empty false)] in my SelectTokens() call, I would expect to get that very same list returned, or an empty array if the comparison value is above 13.

This example works just fine when querying in certain testers such as https://jsonpath.herokuapp.com/ but is seemingly invalid in most other testers, as well as my own C# code, I've attempted to find other alternatives to get this same query functionality, and every time I find a working way to implement this functionality, it turns out to not work within the actual Newtonsoft.Json.Linq.SelectTokens() method that I'm using.

It seems like whenever I try to use the $ operator within the actual query, it just refuses to work within newtonsoft's implementation of jsonpath, and I can't seem to find people trying to achieve the same thing as me, so I'm just curious if there's an easy way to achieve this that works with newtonsoft's implementation.

This is the closest match for what I'm trying to do, although it's for a single token instead of an array, but it too, only works within specific testers JsonPath: Selecting root level field if satisfies a condition

A Sad Shoe
  • 134
  • 6

1 Answers1

1

Jayway (the heroku link you posted) does some things that aren't supported by traditional JSON Path (and probably won't be supported by the specification). Specifically in your case, the empty false isn't a well-known syntax, so I'm not surprised that other implmentations don't support it.

I can see where something like

$[?(@[*].unitPrice>=10)]

operating on

[
  [
    {
      "unitPrice": 5
    },
    {
      "unitPrice": 13
    }
  ],
  [
    {
      "unitPrice": 4
    },
    {
      "unitPrice": 8
    }
  ]
]

would yield the first array but not the second, but as far as the spec, we haven't gotten to this kind of expression where the inner query returns multiple values. Honestly, I think this is a good example for sparking such a discussion. Once it's in the spec, implementations should fall in line with it.

I'm not sure what Newtonsoft supports, but for what it's worth, JsonPath.Net (disclaimer my implementation) also doesn't support this yet. You can play with it at https://json-everything.herokuapp.com/json-path (I just put the site up, so the site may have some bugs, but the library is solid :) ).

Sorry, it's not really an answer so much as an explanation of the state of things.

gregsdennis
  • 7,218
  • 3
  • 38
  • 71
  • While it doesn't serve as a direct solution, it does help a lot in saying that it's not in the spec, meaning I'll probably have to continue looking for a quickfix to it, or create an ugly mix of looping and splitting the query up to get the same functionality. I'm just amazed that something like applying a simple $.length is not really possible within an inner query, as this would also be a way to solve the problem, not the most elegant solution, but a solution. I'll let the question stay open for a few days, in case someone smarter than me finds a good solution to it – A Sad Shoe Aug 31 '21 at 09:31
  • `$.length` is commonly supported (although I don't know what form it'll end up in the spec) because it was in Goessner's original blog post where he proposes the syntax. Granted, this is due to it being valid in JS, which is the original implementation, which is one reason why we're considering changing it. Still, I don't see how knowing the length of the array would help solve your particular issue. – gregsdennis Aug 31 '21 at 13:05