-
Notifications
You must be signed in to change notification settings - Fork 20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
filtering w/o child selection #109
Comments
You can already do this in the existing syntax:
This first selects the nodes under
The one thing we don't have a syntax for is negative selection, e.g. selecting everything except |
@gregsdennis, IMO what you suggest might work only by accident (or deliberate extension of the semantics by some implementations), but according to the wording of the current draft it should not. Please correct my reasoning in the following:
|
Yeah, I think you're right. Mine would return nothing. What you're looking for is more along the lines of
except that it omits We have discussed allowing If such a thing were to be supported, you could do
|
Thanks for the answer. Yes, the examples in the draft (Table 6) have the function And then, even such key-accessing function would not allow to write a path with the desired semantics of “select the whole (root) object if it satisfies the given predicate”, as there would be no place where the initial singleton nodelist could be made into an array to be filtered. Please note, that I am not looking for a solution to any specific problem. My actual use case needs a special JSONPath implementation anyway, so I have simply extended what is currently in the draft by independent filtering (using the By the way, I would be interested to learn how much the standardization effort here is (only) aimed at codifying what the existing implementations are doing, or, in another terms, how strong the requirement of backwards compatibility with status quo is. I see some possibilities for streamlining the semantics, but things could potentially break here and there, so I am uncertain if it even makes sense to share those here. |
You'd probably be interested in reviewing our charter and that there's an existing project to compare various implementations' levels of support. In summary, we are interested in not breaking existing implementations as much as possible, but that's secondary to creating a query language that makes sense. For example, @goessner's original blog post mentions that expressions are to support the syntax of the environment in which that they're run (e.g. Javascript, Python, etc.). However we determined that this doesn't support interoperability well, so we have to define our own syntax for expressions. |
@grzegorz-herman : You are correctly pointing to a certain insufficiency of JSONPath here. I would like to elaborate here a little more. Both arguments ... {
"a": 1,
"b": 2,
"c": 3
} [
1,
2,
3
] will select against the query
So it is vitally important for Note that this has nothing to do with the fact, that we are iterating over the root node. The enability to filter during iteration against the index is inherent. {
"obj": {
"a": 1,
"b": 2,
"c": 3
}
} also won't work via We simply have no mechanism yet to get the node-index during iteration. Imagine, we had the symbol @grzegorz-herman: In this context I do not understand ...
... as Having functions like ... do I miss out here something ? Thanks -- |
It may be interesting to compare how this requirement would be met in JSONiq, an ISO/IEC approved, OASIS standard. In the JSONiq syntax, one way would be:
Output:
|
... interesting ...
|
I think I prefer the function syntax. It opens the door for other functions. |
@gregsdennis , I don't think it does, open the door for other functions. This is based on prior experience with supporting functions in two JSONPath implementations (C++ and C#), one allowing for custom user defined functions, and also on prior experience with two JMESPath implementations (C++ and C#) with built in functions as per the JMESPath Specification. I had earlier suggested Of course, an implementation could support |
Introducing functions also brings permanent temptation to add new functions to the list; it's not bad in itself, but it requires a good versioning strategy for JSONPath. And user-defined functions can cause interoperability problems. We should think twice before opening this door. On the other hand, introducing "current index" symbol binds the operation to current context. With functions we can build queries like |
And if we use, for example ,
That can be quite a powerful syntax. |
The discussion seems to focus more and more on accessing the current key/index. I just wanted to point out that, while such access would indeed solve the example problem, the real intent/question of this issue is different: should JSONPath have a filtering construct operating on the “current list of values”, not tied to child selection. I hope this question does not get lost. Thanks! |
I've re-read your inital post:
In fact, we may be lacking an intersection operation over unions. Some possible examples of this:
In both cases I don't know if these examples look more "intuitive" than semantics of "alternative filtering" originally proposed by @grzegorz-herman or not. As for me personally, concept of intersection is more natural. If we're working with sets, why not use classic set operations? P.S.:
And so does mine PHP implementation (which I've tried to implement as close as possible to JayWay's), but I think that it's absolutely ugly. |
I find the second version somewhat weird: on the left-hand side of the intersection operator we have indices, while on the right – a predicate on values. You can view the first as either an intersection of two unions, or as a regular child selection (
I wholeheartedly agree! |
Union (at least on the level of idea) is just a combination of selectors, it allows you to mix any predicates, like this: Update: I've looked over draft and ensured that union is defined like this:
|
And yes, you're right in that your |
@remorhaz , Possibly follow XPath 2 and later approach to support union and intersect operators? Union ("|") to combine the nodes returned by two or more paths, intersect to return the nodes common to both paths? And allow these operators to be grouped with left and right parentheses? It could be argued that this is a natural evolution of JSONPath, much as XPath 1 evolved. It could also be argued that that's not JSONPath anymore. |
@danielaparker, yes, the "problem" is that union syntax evolved naturally to In fact, we can place all this grammar into
And get something like this:
That could be translated to following functions:
Of course this syntax has tons of pitfalls, but it follows XPath way in general. But we also can follow another way:
In other words, if we defined union like In this case, @grzegorz-herman 's problem salvation will be written like this:
What would you say? |
On Thu, 9 Sep 2021, 19:06 Edward Surov, ***@***.***> wrote:
@danielaparker <https://github.com/danielaparker>, yes, the "problem" is
that union syntax evolved naturally to [..., ...] in JSONPath - where ,
works like | in XPath and there's no grouping. I would like to find the
way not to break this paradygm.
In fact, we can place all this grammar into union-entry. We can make two
entries:
- "nested union" entry (.., ...);
- binary intersect operator over entries.
And get something like this:
$['a', ('b', 'c') intersect ***@***.*** == true)]
That could be translated in a following functions:
union(
index('a'),
intersection(
union(
index('b'),
index('c'),
),
***@***.*** == true),
)
Of course this syntax has tons of pitfalls, but it follows XPath way in
general. But we also can follow another way:
$['a', {['b', 'c'], ***@***.*** == true)}]
In other words, if we defined union like [..., ...], then why not follow
the naturally evolved pattern and define intersection like {..., ...}?
And I see no problems in nesting these structures.
In this case, @grzegorz-herman <https://github.com/grzegorz-herman> 's
problem salvation will be written like this:
${['a', 'b', 'c'], ***@***.*** == true)}
What would you say?
I personally find that syntax a little obscure.
Also, it would be good to know we are satisfying a usecase which can't
easily be satisfied in another way.
… —
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#109 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAAXF2IAXGXJD2YOV3SPWCLUBDZR5ANCNFSM5ATLPCKQ>
.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>.
|
Reading the first suggestion made me feel woozy :-) I thought the second was easier on the eyes. I don't love or hate the notation, and could probably get used to it. I'm not personally enthusiastic about |
112 output:
(Please read the minutes for more details. JSONPath-base is about selection, not projection. |
First of all, thanks for the standardization efforts!
Unless I am missing something, the current draft (https://datatracker.ietf.org/doc/html/draft-ietf-jsonpath-base-01) allows filtering only in the context of child selection. I understand the semantics of
[?(<predicate>)]
as follows:<predicate>
on each subitem (with the special selector@
denoting the subitem),The problem I see is that there seems absolutely no way to filter the current list of items. In some situations, one can work around it, but sometimes not. Assume I have a value
and I would like to select those of subobjects with keys "a", "b" or "c" (but not "d") whose element "v" is true (i.e., the resulting list should contain
{ "v": true, "w": true }
and{ "v": true, "w": false }
). I cannot apply the filtering at the top level, as it would include the key "d", I cannot apply it one level below as it would have to include "w", and there are no other levels.Imagine that we had an independent filtering selector, say
{<predicate>}
, with the semantics of evaluating<predicate>
on each current item (with@
denoting the item) and leaving those which satisfy it (note: I am not proposing this exact syntax here, just the semantics). Then I could intuitively solve the example above with$['a','b','c']{@.v}
.(as a side note, with the above the syntax
[?(<predicate>)]
would become equivalent to[*]{<predicate>}
)Some implementations (jayway IIRC) actually “solve” the problem above by applying the filtering predicate in
[?(...)]
to items or subitems, apparently depending on whether the items are arrays or not. IMO following this path in the standard is a bad idea, as it can quickly become confusing (what if the list contains a mixture of arrays, objects, and primitives?).Please, consider adding an independent filtering selector to the standard!
(as another side note, binding the “current item”
@
is currently also attached to filtering, do you think it could be worthwhile to make it independent as well?)The text was updated successfully, but these errors were encountered: