Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
    hell-racer
    @hell-racer
    !!(vlan_config[?description == 'Another vlan'])
    hell-racer
    @hell-racer

    If this expression is used as a condition inside more complex expression, you can use it simply as vlan_config[?description == 'Another vlan'], e.g.:

    vlan_config[?description == 'Another vlan'] && 'result1' || 'result2'

    If you need exactly true/false then use the first one.

    Alestor
    @Alestor
    Thank you! Both examples are really helpful.
    Alestor
    @Alestor

    Got another one driving me crazy:

    {
       "list":[
          {
             "grades":[
                "c",
                "d",
                "e",
                "f"
             ],
             "student":"Donald"
          },
          {
             "grades":[
                "a",
                "b",
                "e",
                "f"
             ],
             "student":"Dagobert"
          },
          {
             "grades":[
                "a",
                "b",
                "c",
                "d"
             ],
             "student":"Pluto"
          }
       ]
    }

    Let's say I want to find all students with grade a, I simply do list[?grades[?starts_with(@,`a`)]].student . If I want to find students without an a in their grades a simple not-expression like list[?grades[?!starts_with(@,`a`)]].student doesn't do the trick.

    hell-racer
    @hell-racer
    Why starts_with?
    You need contains, no?
    Alestor
    @Alestor
    Same Problem with contains
    If I use the not-expression on grades I'll get the entire list back. No matter if I use contains or starts_with
    hell-racer
    @hell-racer

    With 'a':

    list[?grades[?@ == 'a']].student

    Without 'a':

    list[?!(grades[?@ == 'a'])].student
    Using contains:
    list[?contains(grades, 'a')].student
    list[?!(contains(grades, 'a'))].student
    Alestor
    @Alestor
    makes sense, thank you again :)
    fireundubh
    @fireundubh
    just wanted to say the above example with the @ token was really helpful and should be on the Examples page
    Stephane Landelle
    @slandelle

    Hi there,

    I have a question regarding literal wrapping.
    According to the JMESPATH specification, the wrapping character is supposed to be backtick:

    literal           = "`" json-value "`"

    However, I see lots of examples in this chat using simple quotes and backticks interchangeably.
    And indeed the JMESPath implementation used in the online evaluator supports simple quotes as well.

    But then, other implementations don't, eg the Java one.

    IMHO, this is a bug and all implementations should strictly abide to the specification (that's the whole point of JMESPath compared to JsonPath).

    (original discussing here: https://community.gatling.io/t/jmespath-is-not-finding-a-json-object/6995)

    Thoughts?

    hell-racer
    @hell-racer
    Hi! Can you please provide an example of single quotes used for json literals?
    Stephane Landelle
    @slandelle

    @hell-racer There's one in the Gatling forum post I provided.

    {
    "status":"GOOD",
    "fruits":[
      {
        "name":"Apple",
        "details": {
           "size":500
          }
      },
      {
        "name":"Cherry",
        "details": {
            "size":100
          }
      }]
    }

    On https://jmespath.org/, both following expressions work.

    With quotes:

    fruits[?details.size >= '500']

    With backticks:

    fruits[?details.size >= `500`]

    Only the latter would work with https://github.com/burtcorp/jmespath-java

    hell-racer
    @hell-racer
    Yeah... I meant some examples of single quotes in such context in JmesPath documentation.
    Anyway, in my opinion, it should return empty array when filtering by '500' while the values are numbers in source data.
    Stephane Landelle
    @slandelle

    Yeah... I meant some examples of single quotes in such context in JmesPath documentation.

    I don't think there's one. The documentation matches with the specification.

    Anyway, in my opinion, it should return empty array when filtering by '500' while the values are numbers in source data.

    Agree. I would have liked to open an issue against the JMESPath implementation used for the online evaluator on https://jmespath.org/ but I don't know which one it is. Do you know?

    hell-racer
    @hell-racer
    @springcomp I summon you :)
    It's the JavaScript implementation. I'm going to open an issue on its GitHub project. Thanks a lot for your help!
    Stephane Landelle
    @slandelle
    For the record: jmespath/jmespath.js#85
    hell-racer
    @hell-racer
    Thanks!
    Maxime Labelle
    @springcomp

    @slandelle you are right, you are not crazy šŸ˜.

    For the record, JMESPath used to support strings using this syntax: `this was a string` .
    However, JEP-12 made this syntax obsolete.

    Now, the grammar is much clearer. You can only have:

    • quoted-string : simple JSON strings easy to input using simple quotes. e.g 'hello world!'.
    • raw-string literals : JSON values typed verbatim (except, backtick must be escaped). e.g `"{}`" would be an empty JSON object. Please, note that a JSON string has surrounding double quotes, and thus mus be input like so `"this is a string"` .
    The JavaScript implementation did not change as part of JEP-12 and supports both the old and new way of expressing strings. I suspect this is for compatibility reasons.
    Maxime Labelle
    @springcomp

    Your question is raised in the context of numeric literals. JMESPath does not support JSON numbers in its grammar. So those must be input using raw-string literals. Thus:

    • fruits[? details.size >= `500` ] filters all fruits whose size is greater than number 500.
    • fruits[? details.size >= '500' ] filters all fruits whose size is greater than string "500". Probably not what you want.

    Comparisons between numbers and strings is currently undefined in the grammar as ordering operators are only valid between two numbers. However, popular implementations do make some attempt to cast the string to a number before performing the comparison, so it mostly works even though it is not standards-compliant.

    Blaine Morgan
    @nbmorgan
    Newbie question: What does JMES stand for?
    hell-racer
    @hell-racer
    https://jmespath.org/contents.html
    "JSON Matching Expression paths"
    Nolan Woods
    @innovate-invent
    the authors name is also James
    Maxime Labelle
    @springcomp
    @/all we are making good progress trying to standardize some improvements to JMESPath. Please, feel free to share your feedback and comments.
    Stephane Landelle
    @slandelle

    Comparisons between numbers and strings is currently undefined in the grammar as ordering operators are only valid between two numbers. However, popular implementations do make some attempt to cast the string to a number before performing the comparison, so it mostly works even though it is not standards-compliant.

    If you guys are considering JMESPath 2.0, should this String comparison be made a standard?

    Maxime Labelle
    @springcomp
    @slandelle I have specified your request. However, Iā€™m not sure I agree with implicit conversions, after all...
    msouilhi
    @msouilhi
    I would extract the keys for this dictionnary to get kas_sub.med , kas_sub.test
    {
     "FACTS_ENTRY": {
            "kas_sub.med":  "true",
            "kas_sub.test":  "true"
    }
    Nolan Woods
    @innovate-invent
    msouilhi
    @msouilhi
    @innovate-invent i am using it inside a playbook in ansible and i am new to jmespath so i would use it like this keys(FACTS_ENTRY)?
    hell-racer
    @hell-racer
    Yep
    (probably you've tried it at https://jmespath.org/ and it didn't work because you missed one closing curly brace in your input json)
    msouilhi
    @msouilhi
    thank you so much guys i will try it right now
    hansenjohansen
    @hansenjohansen:matrix.org
    [m]
    I've got a JSON output that looks like the (simplified) below:

    {
    "Code": 1000,
    "GlobalServers": [
    {
    "Name": "bar",
    "Country": "IS",
    "Status": 1,
    "Servers": [
    {
    "Name": "foo",
    "Status": 1
    }
    ]
    }
    ]
    }

    But I am struggling to filter it.
    GlobalServers[?Status==1].... works
    but then if I try
    GlobalServers[?Status==1].Servers[?Status==1] ...I get no ouput

    hell-racer
    @hell-racer

    Hi! At this point

    GlobalServers[?Status==`1`].Servers

    ... you have an array of arrays:

    [
      [
        {
          "Name": "foo",
          "Status": 1
        }
      ]
    ]

    So you have to flatten it and stop the projection before filtering:

    GlobalServers[?Status==`1`].Servers[]|[?Status==`1`]

    Output:

    [
      {
        "Name": "foo",
        "Status": 1
      }
    ]
    hansenjohansen
    @hansenjohansen:matrix.org
    [m]
    I see, that makes sense. Thanks for the clear explanationhell-racer (hell-racer) . So I guess the only issue then is that if I flatten it, I loose the ability to get a key value from the parent ? (e.g. if I wanted to pull "Country" value from the parent in addition to the data from the filtered child nodes)
    hell-racer
    @hell-racer
    It could be possible to filter while keeping nesting level. Just post exact shape of output you need (based on input you've posted), and I'll try to come up with the query.
    hell-racer
    @hell-racer
    If you need just the Servers and Country:
    GlobalServers[?Status==`1`].{ Servers: Servers[?Status==`1`], Country: Country }
    If you need everything while filtering both levels:
    GlobalServers[?Status==`1`].merge(@, { Servers: Servers[?Status==`1`] })
    hansenjohansen
    @hansenjohansen:matrix.org
    [m]
    Sorry for the delay in reply @hell-racer , I'll go test these and let you know.
    hansenjohansen
    @hansenjohansen:matrix.org
    [m]
    @hell-racer: The suggestion with merge(@) worked great. Thank you again !
    hell-racer
    @hell-racer
    nice :)
    hansenjohansen
    @hansenjohansen:matrix.org
    [m]

    @hell-racer: There's one more thing, I was hoping to find the answer myself but I can't find the right way to do it. Building on your "GlobalServers[?Status==1].merge(@, { Servers: Servers[?Status==1] })".....

    The GlobalServers parent node has a "score" value for each entry, I would like to only return the node for the highest score (that also matches the filter).

    So far the nearest I have managed to get is this:
    "max_by(GlobalServers[],&Score).merge(@, { Servers: Servers[?Status==1] })"

    But no matter how I try to integrate the original GlobalServers filter, I can't manage do to it. I've tried putting max_by() before the filter, after the filter, inside the filter ... jmespath complains each time.