jmespath / jmespath.test

JMESPath compliance tests.
http://jmespath.org
6 stars 5 forks source link

Filters not working intuitively #15

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?

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"
        }
      ]
    }
  ]
}
rianwouters commented 6 years ago

@apatrida ran into a similar issue:

lorem[?name=='ipsum'].dolor[?name=='sit']

input:

{
  "lorem": [
    {
      "name": "ipsum",
      "dolor": [
        {
           "name": "sit"
        },
        {
           "name": "amet"
        }
      ]
    },
    {
    }
  ]
}

expected:

[
  {
    "name": "sit"
  }
]

actual:

[]

another workaround I found:

lorem[?name=='ipsum'].[dolor][][?name=='sit']