@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"`
.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.
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?
{
"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
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
}
]
GlobalServers[?Status==`1`].merge(@, { Servers: Servers[?Status==`1`] })
merge(@)
worked great. Thank you again !
@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.
It returns ERR_CONNECTION_RESET :(.
Ok, on the site https://jmespath.org/ given input:
{
"Code": 1000,
"GlobalServers": [
{
"Name": "bar1",
"Country": "IS",
"Score": 1,
"Servers": [
{
"Name": "foo1",
"Status": 1
},
{
"Name": "foo2",
"Status": 2
}
]
},
{
"Name": "bar2",
"Country": "US",
"Score": 2,
"Servers": [
{
"Name": "foo",
"Status": 1
},
{
"Name": "foo2",
"Status": 2
}
]
}
]
}
Your query:
max_by(GlobalServers, &Score).merge(@, { Servers: Servers[?Status==`1`] })
Returns:
{
"Name": "bar2",
"Country": "US",
"Score": 2,
"Servers": [
{
"Name": "foo",
"Status": 1
}
]
}
[]
in the GlobalServers[]
.
1
] })" works. But that's not my problem. I still need to integrate the original "GlobalServers[?Status==1
]" parent filter and I can't find a way to do that in conjunction with max_by()
1
].max_by(GlobalServers, &Score).) or something like that
GlobalServers[?Status == `1`]|max_by(@, &Score).merge(@, { Servers: Servers[?Status==`1`] })
The problems with
GlobalServers[?Status==1].max_by(GlobalServers, &Score) ...
... are these:
.
after that, it will evaluate everything after the .
in context of single element of the filtered array, so max_by
will treat a single item as array and try to find max in it. So you have to stop the projection, to allow the next function to operate on the entire filtered array..
to |
you are now in context of the filtered array of GlobalServers
, so you have to use @
to refer to it instead of GlobalServers
.