Open darrencruse opened 4 years ago
Update: after I writing the above mainly from playing in try.jsonata.org I remembered: we are successfully using the [*] syntax against json api payloads when we use jsonata from node.js!!
after going back and trying examples of those json payloads in try.jsonata.org I came to realize even the example I gave above will work so long as "b" is not numeric if it's any other type it seems to work e.g. this doesn't give the "no match" response with a[*].b as the expression all I've done is change b from the number 1 to the string "fred":
{
"a": [
{
"b": "fred"
}
]
}
could it be that "*" is being seen as the times operator because b is numeric?
*
is a wildcard (https://docs.jsonata.org/predicate#wildcards) and will select all of the properties of a
. If the expression inside the square brackets evaluates to a number or array of numbers, then they are interpreted as the index(es) of a
to select (1
and 2
) (see https://docs.jsonata.org/predicate#wildcards). Since there is only one a
(at index 0), then nothing is selected. If it evaluates to fred
, then it is non-numeric and gets cast to a Boolean (true) and therefore selected.
To select the b
property(ies) of any a
, just use a.b
. And, as you've observed, if you want singleton results to be in an array, then use a[].b
or a.b[]
(see https://docs.jsonata.org/predicate#singleton-array-and-value-equivalence final paragraphs)
Thanks Andrew read your comments and re-read the sections u linked I think I'm close to following but still not quite there
going back to this in the repl:
{
"a": [
{
"b": 1,
"c": 2
}
]
}
I'm certainly clear when e.g. "a[c = 2].b" gives me back 1
then going thru your explanation u said: "* is a wildcard (https://docs.jsonata.org/predicate#wildcards) and will select all of the properties of a."
I got that u are stepping me thru the whole expression from the beginning so in the repl I tried just "a[*]"
that gives me no match but "a.*" but "a.*" does give back the [1, 2] u mention in your next sentence
(mental note to self: unlike in javascript with jsonata I should not expect dots and square brackets to act the same)
and I follow the idea e.g. I tried an example where I added a couple more array elements and I noticed like "a[[0,1]]" lets me select the first two elements that makes sense
so in my original example only one element at 0 none at 1 or 2 therefore no match got it
so switching to my second example:
{
"a": [
{
"b": "fred"
}
]
}
I see that "a.*" just returns "fred"
and you said that's just interpreted as a predicate returing a truthy value
and I get your point u r saying if that seems confusing it's partly just my expression is not idiomatic
Anyway u can close these two issues I made if u want fwiw jsonata has proved helpful for our project so far e.g. we've been using it for some "computed attributes" doing e.g. simple arithmetic against our json api payloads
hopefully these examples in my two issues are not typical and for simple cases our users won't need to think things thru in this depth
we are migrating code that uses lodash get to jsonata
(glossing over some details but) our end users today actually see our lodash get paths (they wind up stored in our database)
short of them learning all of jsonata we liked the simplicity of saying to them "where you previously used a path like e.g. to get the first:
now put * instead of 0 to get them all:
But In try.jsonata.org I made this little json:
here's a try.jsonata.org link to the above example btw: https://try.jsonata.org/YST1DYWh-
At first I thought it was a bug that that the expression "a[*].b" returns "no match" instead of 1 ? (alternatives e.g. a.b, a[0].b, a[c = 2].b all work but shouldn't a[*].b also work?)
But after writing all this I looked back at the jsonata docs and realized maybe I just dreamed it maybe a predicate of "[*]" is not actually supported?
I have some familiarity with JSONPath maybe that's where I got the idea I just tried in the repl at https://jsonpath.com and a[*].b does work with JSONPath
last question: assuming this isn't a bug and it truly isn't supported - I'm leaning toward telling our users that where they used to use e.g. "a[0].b" trying using "a[].b"
i.e. a general advice to replace any of their array indexes with just empty brackets
the reason I'm leaning this way is the default jsonata behavior to return the unwrapped singleton value when the match is just one element in an array is problematic for us we need it to consistently return an array unless it's a simple object only path with no arrays involved at all
I need to play with more examples myself but does it seem a reasonable approach?