Change:
Add array slicing, filters, and lists. Fixes URL
Would it be useful to have references to indications of implementation consensus in this ticket?
Probably best to put such things in issues rather than PRs, so I'll add something to URL
Currently the spec only permits , ..[]..[1]. I think it would be beneficial and trivial to also allow the other bracketed query syntaxes: (I expect this should already be supported since is, but it doesn't seem to be) -
Descendants with quoted member names, such as , are already supported:
Here are the relevant tests from the comparison project. Lack of consensus for descendant/filter: URL URL Consensus for descendant/list: URL (Context: URL)
Currently, the descendant selector spec allows some non-determinism which may be unexpected. The spec currently says that in the resultant nodelist from the descendant selector: nodes occur before their children, and nodes of an array occur in array order. This sometimes allows multiple orderings when the result includes children of a node, but not the node itself. For example, with the document: the selector could, according to the spec, produce the nodelist: or the nodelist: This is surprising given that there are no objects in the document, since object ordering is the usual source of non-determinism. We could change the spec to constrain the order of traversal rather than the order of the resultant nodelist, but this seems to be getting into implementation detail. Is the current approach acceptable?
Hi Glyn, I treated the descendant-selector and the following object member name, index-selector, or wildcard as two separate steps. In order for the next step to be able to return values as per the examples, the first node that needs to be presented by the descendant-selector to the next step is the entirety of the current node (in case of the whole document). Given what I've written above, in the example, the whole document is always the first thing presented to the index selector. Given this, when the descendant-selector goes into the array, it will present the nodes and to the index selector. (Note that node is a child of node , so comes after.) Since the selector presumably only applies to arrays, it only applies to nodes and , and the "nodes before children" gives an explicit order, I don't see how the result could be . Have I missed something? Is it a matter of updating the semantics to say the entirety of the current node is looked at first? (Side note - the spec is not as clear on the element-index only applying to arrays. It's implied, but not stated as clearly as it is for quoted-member-names and objects.) Kind Regards, Graham
I think something like that is probably desirable, but without unduly constraining implementations. Thanks. I'll take a look at that with an editorial PR.
I think rewording the second condition ("nodes of an array occur in array order") achieves the desired ordering: nodes of a given array, and descendants of nodes of the given array, occur in array order.
I'm still here. I'm not sure that anything needs to be updated. I think the current text (node then descendants) is sufficient to guarantee the correct ordering. In this case, is processed, producing then is processed, producing It must be this way because of array ordering. gives the (ordered) node list . Of those, we take the first elements of arrays, which is from and from . I'm really struggling to see how the current wording can yield anything else.
The behaviour of is interesting. With the document: and the selector , Nebhale produces a result obeying the reworded conditions (but starts the nodelist with ): Jayway and Goessner place after , contrary to the reworded conditions: and Gatling doesn't even get close to the spec:
The problem with the current wording is that it allows too much freedom in the resultant nodelist. The result is allowed because: nodes occur before their children (since isn't a child of or vice versa), and nodes of an array occur in array order (since and are not nodes of the same array). I think you are interpreting differently from the spec. You seem to be regarding it as a combination of and ...... whereas the spec allows only strict descendants.)
It probably should say that this is the node order of the node list that describes the entire input JSON value. A node list is a subset of that novelist, preserving order.
Hmmm. That's a bit tricky because there isn't necessarily a unique node order (because objects are not ordered). So, at best, it describes a collection of ordered nodelists and then the resultant nodelist is a subset of any one of those nodelists, preserving order. I think the reworded condition above captures the constraint more simply.
These rules necessitate that 0 come before 1 in the above case. Let's look at the case because it's more interesting given the array as the first item. Evaluating the array in sequence and nodes before children has two possible processes: Evaluate each item, evaluating its children before moving to the next item. Order of processing is , , , , . Queue each item, queuing its children as the item is processed, eventually running through the queue. Order of processing is , , , , . In both cases, the resulting node list is . You never get before , which means that you will always get in the first example. The only question is whether does 1 or 2 from above.
I would agree, if the spec required evaluating the array in sequence and nodes before children, but it doesn't. It only talks about the order of the resultant nodelist. What text in the spec makes you think it is talking about the order of evaluation, as such? Of course, the order of the resultant nodelist implies some things about the order of evaluation, but it doesn't say anything about the ordering of nodes relative to the descendants of their siblings.
I thought we already defined this. I'll need to consult the spec again.
It's surprising the comparison project has the for applied to :
Perhaps the others also did what I did and treated the and what follows as two separate steps? The descendant part only visits each of the nodes leaving it to the second part to process what's there. This allows the same code to be used as for the non-descendant version of the same selector. (It also means that my descendant selector allows list selectors because I removed the other types of selectors in favour of that.) If instead is treated as a single step and takes care of both jobs, descending and wildcard, then I could see how the following alternate result could be returned: The definitions at the top of this JSONPath document mentions a "transitive closure over the chidlren relation" but that was too mathematical for me. I had a look at XPath's descendant-or-self but the spec didn't tell me exactly what to expect. I tried the following XML using an : An XPath of produced something like the "alternate result" I've given above:
Yes, that's what I've done in my implementation as well. But in terms of the specification, must always be coupled with another selector, whether that's a name, wildcard, or bracket-syntax. As such it makes sense to define it in conjunction with the "second" selector. There's some discussion as well.
All the spec needs to require is that there is an input order that the output nodelist is a subsequence of. After you have banged it into shape to actually do this, I’m not so sure… Grüße, Carsten
That would work, but we'd need to define "input order" carefully as it's not necessarily unique because of objects.
NAME I had a go at the "input order" approach. See the in PR 218.
Great. Maybe we should give orders that satisfy the criteria a name; with your text, maybe "visit order"?
Happy to attempt something once URL lands. I feel that "visit order" is a little too generic. I would prefer a more specific term such as "array preorder". WDYT? (Happy to continue this thread here, but feel free to move to a fresh editorial issue if you prefer.)

Discussion:
3.5.7.1. The descendant selectors start with a double dot ".." and can be <del> followed by an object member name (similar to the "dot-selector"), by an "index-selector" acting on objects or arrays, or by a wildcard. </del> <ins> followed by an object member name (similar to the "dot-selector"), a wildcard (similar to the "dot-wild-selector"), an "index-selector", "index-wild-selector", "filter-selector", or "list-selector" acting on objects or arrays, or a "slice-selector" acting on arrays. </ins> Note that there is no "bald" descendant selector "..".

The "descendant-selector" selects certain descendants of a node: the "..<name>" form (and the "..[<index>]" form where "<index>" is <del> a "quoted-member-name") selects those descendants of the node that are member values of an object with the given member name. </del> <ins> a "quoted-member-name") selects those descendants that are member values of an object with the given member name. </ins> <del> the "..[<index>]" where "<index>" is an "element-index" selects those descendants of the node that are array elements with the given index. </del> <ins> the "..[<index>]" form, where "<index>" is an "element-index", selects those descendants that are array elements with the given index. </ins> <del> the "..[*]" and "..*" forms select all the descendants of the node. </del> <ins> the "..[<slice-index>]" form selects those descendants that are array elements selected by the given slice. the "..[<filter>]" form selects those descendants that are array elements or object values selected by the given filter. the "..[*]" and "..*" forms select all the descendants. </ins> The resultant nodelist is ordered as if: