jmespath / jmespath.js

Javascript implementation of JMESPath, a query language for JSON
http://jmespath.org
Other
783 stars 97 forks source link

Filters not working intuitively #37

Open apatrida opened 6 years ago

apatrida commented 6 years ago

Maybe it is my misunderstanding, but with this data:

 {
            "a": {
                "b": [{
                    "c": {
                        "d": {
                            "e": "foo"
                        }
                    },
                    "something": "bar"
                }, {
                    "c": {
                        "d": {
                            "e": "miss"
                        }
                    }
                }]
            }
}

With the following query, nothing returns:

a.b[*].c.d[?e == 'foo']

But this does work:

a.b[*].c.d|@[?e == 'foo']

And in JSON Path (JayWay implementation for example):

a.b[*].c.d[?(@.e == "foo")] is the equivalent.

Is this intentional? they seem functionally equivalent but obviously are not. This fails in the playground (JavaScript), but also fails in the Java implementation.

Is this a spec issue? As designed? Common bug in all implementations? Where do we report something like this that seems to be prevalent across all of JMES?

(https://github.com/jmespath/jmespath.test/issues/15)

apatrida commented 6 years ago

Another odd example, using contacts JSON below:

Fails:

contacts[?addresses[*].state == 'NY'].[firstName, lastName]

Succeeds:

contacts[?addresses[0].state == 'NY'].[firstName, lastName]

or

contacts[?addresses[?state == 'NY']].[firstName, lastName]

and the JSON Path (Jayway) equivalent is:

contacts[?(@.addresses[?(@.state == "NY")])]

So I guess it is the same as that, in that a projection cannot be used within a truthy expression?

INPUT JSON:

{
  "contacts": [
    {
      "firstName": "John",
      "lastName": "Smith",
      "isAlive": true,
      "age": 25,
      "addresses": [
        {
          "streetAddress": "21 2nd Street",
          "city": "New York",
          "state": "NY",
          "postalCode": "10021-3100"
        }
      ],
      "phoneNumbers": [
        {
          "type": "home",
          "number": "212 555-1234"
        },
        {
          "type": "office",
          "number": "646 555-4567"
        },
        {
          "type": "mobile",
          "number": "123 456-7890",
          "faceTime": true
        }
      ],
      "spouse": null
    },
    {
      "firstName": "David",
      "lastName": "Williams",
      "isAlive": true,
      "age": 34,
      "addresses": [
        {
          "streetAddress": "4545 W 51st",
          "city": "New York",
          "state": "NY",
          "postalCode": "10021"
        }
      ],
      "phoneNumbers": [
        {
          "type": "home",
          "number": "212 555-9919"
        },
        {
          "type": "mobile",
          "number": "212 555-1111",
          "faceTime": false
        }
      ]
    },
    {
      "firstName": "Bridget",
      "lastName": "Jamenson",
      "isAlive": true,
      "age": 23,
      "addresses": [
        {
          "streetAddress": "318 N. Rosemont",
          "city": "Dalles",
          "state": "TX",
          "postalCode": "75208"
        }
      ],
      "phoneNumbers": [
        {
          "type": "home",
          "number": "214 555-9913"
        },
        {
          "type": "mobile",
          "number": "214 555-3300",
          "faceTime": true
        },
        {
          "type": "office",
          "number": "214 555-0001"
        }
      ]
    }
  ]
}
jancassio commented 6 years ago

@apatrida I did with this query:

contacts[?addresses[?state == 'NY']][firstName, lastName]

I guess, [*] isn't need because [?...] is doing filter over all indexes