ajson icon indicating copy to clipboard operation
ajson copied to clipboard

Add filter for values

Open voltento opened this issue 4 years ago • 6 comments

Hello! It would be great if there was a possibility of filtering objects by value as it's for arrays values. F.e.:

  1. Array values Here is the data: {"data": ["b"]} And the filter: $.data[?(@ == ‘b’)] will bring the node. Works with arrays fine!

  2. Object values Here is the data: { "price": 1} And I'd like to have a filter like this: $.price?(@ == 1) which would return the node

voltento avatar Apr 22 '20 12:04 voltento

Hello! Thanks, I think it could be useful. Will try to implement it in the next release.

spyzhov avatar Apr 24 '20 22:04 spyzhov

This is a very useful feature, still in roadmap to be included in a future release?

aaroalan avatar Nov 12 '21 16:11 aaroalan

I think so. Will implement it in the version v1.X.X.

spyzhov avatar Nov 12 '21 23:11 spyzhov

I started looking at this, but it is not clear how this should be implemented without changing how the current filtering works so maybe allowing this feature but not changing the current implementation.

I encounter this issue:

ParseJSONPath already transform $.data[?(@ == ‘b’)] into []string{"$","data","?(@ == ‘b’)"} which means that $.data[?(@ == ‘b’)] and $.data?(@ == ‘b’) will return the same slice which means that anyone that is using ApplyJSONPath directly is passing only ?(@ == ‘b’).

Ideas:

  1. I thought the expression output could be different e.g [?(@ == ‘b’)] and ?(@ == ‘b’) unfortunately this will break any implementation that is currently calling ApplyJSONPath and passing only expression ?(@ == ‘b’). they will need to change all expressions to include [] in order to have the current filter

  2. Another idea although not present anywhere could be use {} instead [] when the filtering/exp should be applied to the current node e.g $.data[?(@ == ‘b’)] and $.price{?(@ == 1)}. In order to not break the current ApplyJSONPath functionality the commands could be structs instead of strings with a flag that tells if should be applied to the current node and ApplyJSONPath can continue to get []string and create []Command with the flag that tells that filter is in inheritors.

e.g(2) for:

{
  "type": "book",
  "id": "A1234",
  "author": {
    "id": "AA123",
    "name": "Foo"
  }
  "notes": [
    {
      "id": "N1",
      "title": "Some title 1",
      "note": "Nice"
    },
    {
      "id": "N2",
      "title": "Some title 2",
      "note": "Very Nice"
    }
  ]
}
// $.notes[?(@.id=="N1")]
{
  "id": "N1",
  "title": "Some title 1",
  "note": "Nice"
}

// ${?(@.type=="book")}.author
{
  "id": "AA123",
  "name": "Foo"
}

What do you think about this?

aaroalan avatar Nov 17 '21 16:11 aaroalan

Thanks for the suggestions! Unfortunately, I can't implement {...} filter as it is not in the specification, but you can try to add this suggestion to the ietf JSONPath (draft). If it passes, I will implement it :-)

The simplest way, how to implement it without the new filter - to add a new function or operator.

I will try to implement some operators from the https://www.postgresql.org/docs/9.5/functions-json.html , like:

Operator Operand Type Description Example
@> object Does the left JSON value contain the right JSON path/value entries at the top level? '{"a":1, "b":2}' @> '{"b":2}'
<@ object Are the left JSON path/value entries contained at the top level within the right JSON value? '{"b":2}' <@ '{"a":1, "b":2}'

So it will be available to use requests like $..[?(@ @> {"b":2})], but as you can see @ here looks a little out of place here. I probably will change this symbol.

spyzhov avatar Nov 17 '21 20:11 spyzhov

@aaroalan, I created a draft for V1 milestone: #42. The whole project will be rewritten.

spyzhov avatar Nov 21 '21 12:11 spyzhov