rfc9535.original.xml | rfc9535.xml | |||
---|---|---|---|---|
<?xml version='1.0' encoding='utf-8'?> | <?xml version="1.0" encoding="UTF-8"?> | |||
<!DOCTYPE rfc [ | <!DOCTYPE rfc [ | |||
<!ENTITY nbsp " "> | <!ENTITY nbsp " "> | |||
<!ENTITY zwsp "​"> | <!ENTITY zwsp "​"> | |||
<!ENTITY nbhy "‑"> | <!ENTITY nbhy "‑"> | |||
<!ENTITY wj "⁠"> | <!ENTITY wj "⁠"> | |||
]> | ]> | |||
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?> | ||||
<!-- generated by https://github.com/cabo/kramdown-rfc version 1.6.43 (Ruby 3.2. 2) --> | <!-- generated by https://github.com/cabo/kramdown-rfc version 1.6.43 (Ruby 3.2. 2) --> | |||
<?rfc comments="yes"?> | ||||
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft | <rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft | |||
-ietf-jsonpath-base-21" category="std" consensus="true" submissionType="IETF" xm | -ietf-jsonpath-base-21" number="9535" submissionType="IETF" category="std" conse | |||
l:lang="en" tocDepth="4" tocInclude="true" sortRefs="true" symRefs="true" versio | nsus="true" xml:lang="en" tocDepth="4" tocInclude="true" sortRefs="true" symRefs | |||
n="3"> | ="true" updates="" obsoletes="" version="3"> | |||
<!-- xml2rfc v2v3 conversion 3.18.0 --> | <!-- xml2rfc v2v3 conversion 3.18.0 --> | |||
<front> | <front> | |||
<title abbrev="JSONPath">JSONPath: Query expressions for JSON</title> | <title abbrev="JSONPath">JSONPath: Query Expressions for JSON</title> | |||
<seriesInfo name="Internet-Draft" value="draft-ietf-jsonpath-base-21"/> | <seriesInfo name="RFC" value="9535"/> | |||
<author initials="S." surname="Gössner" fullname="Stefan Gössner" role="edit or"> | <author initials="S." surname="Gössner" fullname="Stefan Gössner" role="edit or"> | |||
<organization>Fachhochschule Dortmund</organization> | <organization>Fachhochschule Dortmund</organization> | |||
<address> | <address> | |||
<postal> | <postal> | |||
<street>Sonnenstraße 96</street> | <street>Sonnenstraße 96</street> | |||
<city>Dortmund</city> | <city>Dortmund</city> | |||
<code>D-44139</code> | <code>D-44139</code> | |||
<country>Germany</country> | <country>Germany</country> | |||
</postal> | </postal> | |||
<email>stefan.goessner@fh-dortmund.de</email> | <email>stefan.goessner@fh-dortmund.de</email> | |||
</address> | </address> | |||
</author> | </author> | |||
<author initials="G." surname="Normington" fullname="Glyn Normington" role=" editor"> | <author initials="G." surname="Normington" fullname="Glyn Normington" role=" editor"> | |||
<organization/> | <organization/> | |||
<address> | <address> | |||
<postal> | <postal> | |||
<street/> | <street/> | |||
<city>Winchester</city> | <city>Winchester</city> | |||
<region/> | <region/> | |||
<code/> | <code/> | |||
<country>UK</country> | <country>United Kingdom</country> | |||
</postal> | </postal> | |||
<phone/> | <phone/> | |||
<email>glyn.normington@gmail.com</email> | <email>glyn.normington@gmail.com</email> | |||
</address> | </address> | |||
</author> | </author> | |||
<author initials="C." surname="Bormann" fullname="Carsten Bormann" role="edi tor"> | <author initials="C." surname="Bormann" fullname="Carsten Bormann" role="edi tor"> | |||
<organization>Universität Bremen TZI</organization> | <organization>Universität Bremen TZI</organization> | |||
<address> | <address> | |||
<postal> | <postal> | |||
<street>Postfach 330440</street> | <street>Postfach 330440</street> | |||
<city>Bremen</city> | <city>Bremen</city> | |||
<code>D-28359</code> | <code>D-28359</code> | |||
<country>Germany</country> | <country>Germany</country> | |||
</postal> | </postal> | |||
<phone>+49-421-218-63921</phone> | <phone>+49-421-218-63921</phone> | |||
<email>cabo@tzi.org</email> | <email>cabo@tzi.org</email> | |||
</address> | </address> | |||
</author> | </author> | |||
<date year="2023"/> | <date year="2024" month="February"/> | |||
<area>ART</area> | <area>art</area> | |||
<workgroup>JSONPath WG</workgroup> | <workgroup>jsonpath</workgroup> | |||
<keyword>JSON</keyword> | <keyword>JSON</keyword> | |||
<abstract> | <abstract> | |||
<?line 145?> | <t>JSONPath defines a string syntax for selecting and extracting JSON (RFC 8259) | |||
values from within a given JSON value.</t> | ||||
<t>JSONPath defines a string syntax for selecting and extracting JSON (RFC 8259) | ||||
values | ||||
from a JSON value.</t> | ||||
</abstract> | </abstract> | |||
<note removeInRFC="true"> | ||||
<name>About This Document</name> | ||||
<t> | ||||
Status information for this document may be found at <eref target="https | ||||
://datatracker.ietf.org/doc/draft-ietf-jsonpath-base/"/>. | ||||
</t> | ||||
<t> | ||||
Discussion of this document takes place on the | ||||
JSON Path Working Group mailing list (<eref target="mailto:jsonpath@ietf | ||||
.org"/>), | ||||
which is archived at <eref target="https://mailarchive.ietf.org/arch/bro | ||||
wse/jsonpath/"/>. | ||||
Subscribe at <eref target="https://www.ietf.org/mailman/listinfo/jsonpat | ||||
h/"/>. | ||||
</t> | ||||
<t>Source for this draft and an issue tracker can be found at | ||||
<eref target="https://github.com/ietf-wg-jsonpath/draft-ietf-jsonpath-ba | ||||
se"/>.</t> | ||||
</note> | ||||
</front> | </front> | |||
<middle> | <middle> | |||
<?line 150?> | ||||
<!-- define an ALD to simplify below --> | ||||
<!-- use as {: unnumbered} --> | ||||
<!-- editorial issue: lots of complicated nesting of quotes, as in --> | ||||
<!-- `"13 == '13'"` or `$`. We probably should find a simpler style --> | ||||
<section anchor="introduction"> | <section anchor="introduction"> | |||
<name>Introduction</name> | <name>Introduction</name> | |||
<t>JSON <xref target="RFC8259"/> is a popular representation | <t>JSON <xref target="RFC8259"/> is a popular representation | |||
format for structured data values. | format for structured data values. | |||
JSONPath defines a string syntax for selecting and extracting JSON values | JSONPath defines a string syntax for selecting and extracting JSON values | |||
from a JSON value.</t> | from within a given JSON value.</t> | |||
<t>JSONPath is not intended as a replacement for, but as a more powerful | <t>In relation to JSON Pointer <xref target="RFC6901"/>, JSONPath is not intende | |||
companion to, JSON Pointer <xref target="RFC6901"/>. See <xref target="json-poin | d as a replacement but as a more powerful | |||
ter"/>.</t> | companion. See <xref target="json-pointer"/>.</t> | |||
<section anchor="terminology"> | <section anchor="terminology"> | |||
<name>Terminology</name> | <name>Terminology</name> | |||
<t>The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>", "<bcp | <t> | |||
14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL | The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>", "<bcp14>REQU | |||
NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>", "<bcp14>RECO | IRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL | |||
MMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>", | NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>", "<bcp14> | |||
"<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are to be i | RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>", | |||
nterpreted as | "<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are to | |||
described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and | be interpreted as | |||
only when, they | described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> | |||
appear in all capitals, as shown here.</t> | when, and only when, they appear in all capitals, as shown here. | |||
<?line -18?> | </t> | |||
<t>The grammatical rules in this document are to be interpreted as ABNF, | <t>The grammatical rules in this document are to be interpreted as ABNF, | |||
as described in <xref target="RFC5234"/>. | as described in <xref target="RFC5234"/>. | |||
ABNF terminal values in this document define Unicode scalar values rather than | ABNF terminal values in this document define Unicode scalar values rather than | |||
their UTF-8 encoding. | their UTF-8 encoding. | |||
For example, the Unicode PLACE OF INTEREST SIGN (U+2318) would be defined | For example, the Unicode PLACE OF INTEREST SIGN (U+2318) would be defined | |||
in ABNF as <tt>%x2318</tt>.</t> | in ABNF as <tt>%x2318</tt>.</t> | |||
<t>Functions are referred to using the function name followed by a pair | <t>Functions are referred to using the function name followed by a pair | |||
of parentheses, as in <tt>fname()</tt>.</t> | of parentheses, as in <tt>fname()</tt>.</t> | |||
<t>The terminology of <xref target="RFC8259"/> applies except where clar ified below. | <t>The terminology of <xref target="RFC8259"/> applies except where clar ified below. | |||
The terms "Primitive" and "Structured" are used to group | The terms "primitive" and "structured" are used to group | |||
different kinds of values as in <xref section="1" sectionFormat="of" target="RFC | different kinds of values as in <xref section="1" sectionFormat="of" target="RFC | |||
8259"/>; JSON Objects and Arrays are | 8259"/>. JSON objects and arrays are | |||
structured, all other values are primitive. | structured; all other values are primitive. | |||
Definitions for "Object", "Array", "Number", and "String" remain | Definitions for "object", "array", "number", and "string" remain | |||
unchanged. | unchanged. | |||
Importantly "object" and "array" in particular do not take on a | Importantly, "object" and "array" in particular do not take on a | |||
generic meaning, such as they would in a general programming context.</t> | generic meaning, such as they would in a general programming context.</t> | |||
<t>Additional terms used in this document are defined below.</t> | <t>The terminology of <xref target="RFC9485"/> applies.</t> | |||
<t>Additional terms used in this document are defined below.</t> | ||||
<dl> | <dl> | |||
<dt>Value:</dt> | <dt>Value:</dt> | |||
<dd> | <dd> | |||
<t>As per <xref target="RFC8259"/>, a structure conforming to the ge | <t>As per <xref target="RFC8259"/>, a data item conforming to the ge | |||
neric data model of JSON, i.e., | neric data model of JSON, i.e., | |||
composed of constituents such as structured values, namely JSON objects and arra | primitive data (numbers, text strings, and the special | |||
ys, and | values null, true, and false), or structured data (JSON objects and arrays). | |||
primitive data, namely numbers and text strings as well as the special | ||||
values null, true, and false. | ||||
<xref target="RFC8259"/> focuses on the textual representation of JSON values an d | <xref target="RFC8259"/> focuses on the textual representation of JSON values an d | |||
does not fully define the value abstraction assumed here.</t> | does not fully define the value abstraction assumed here.</t> | |||
</dd> | </dd> | |||
<dt>Member:</dt> | <dt>Member:</dt> | |||
<dd> | <dd> | |||
<t>A name/value pair in an object. (A member is not itself a value. )</t> | <t>A name/value pair in an object. (A member is not itself a value. )</t> | |||
</dd> | </dd> | |||
<dt>Name:</dt> | <dt>Name:</dt> | |||
<dd> | <dd> | |||
<t>The name (a string) in a name/value pair constituting a member. | <t>The name (a string) in a name/value pair constituting a member. | |||
skipping to change at line 159 ¶ | skipping to change at line 135 ¶ | |||
<dd> | <dd> | |||
<t>An integer that identifies a specific element in an array.</t> | <t>An integer that identifies a specific element in an array.</t> | |||
</dd> | </dd> | |||
<dt>Query:</dt> | <dt>Query:</dt> | |||
<dd> | <dd> | |||
<t>Short name for a JSONPath expression.</t> | <t>Short name for a JSONPath expression.</t> | |||
</dd> | </dd> | |||
<dt>Query Argument:</dt> | <dt>Query Argument:</dt> | |||
<dd> | <dd> | |||
<t>Short name for the value a JSONPath expression is applied to. | <t>Short name for the value a JSONPath expression is applied to. | |||
(Also used for actual parameters of function-expressions.)</t> | </t> | |||
</dd> | </dd> | |||
<dt>Location:</dt> | <dt>Location:</dt> | |||
<dd> | <dd> | |||
<t>the position of a value within the query argument. This can be th ought of | <t>The position of a value within the query argument. This can be th ought of | |||
as a sequence of names and indexes navigating to the value through | as a sequence of names and indexes navigating to the value through | |||
the objects and arrays in the query argument, with the empty sequence | the objects and arrays in the query argument, with the empty sequence | |||
indicating the query argument itself. | indicating the query argument itself. | |||
A location can be represented as a Normalized Path (defined below).</t> | A location can be represented as a Normalized Path (defined below).</t> | |||
</dd> | </dd> | |||
<dt>Node:</dt> | <dt>Node:</dt> | |||
<dd> | <dd> | |||
<t>The pair of a value along with its location within the query argu ment.</t> | <t>The pair of a value along with its location within the query argu ment.</t> | |||
</dd> | </dd> | |||
<dt>Root Node:</dt> | <dt>Root Node:</dt> | |||
<dd> | <dd> | |||
<t>The unique node whose value is the entire query argument.</t> | <t>The unique node whose value is the entire query argument.</t> | |||
</dd> | </dd> | |||
<dt>Root Node Identifier:</dt> | <dt>Root Node Identifier:</dt> | |||
<dd> | <dd> | |||
<t>The expression <tt>$</tt> which refers to the root node of the qu ery argument.</t> | <t>The expression <tt>$</tt>, which refers to the root node of the q uery argument.</t> | |||
</dd> | </dd> | |||
<dt>Current Node Identifier:</dt> | <dt>Current Node Identifier:</dt> | |||
<dd> | <dd> | |||
<t>The expression <tt>@</tt> which refers to the current node in the context | <t>The expression <tt>@</tt>, which refers to the current node in th e context | |||
of the evaluation of a filter expression (described later).</t> | of the evaluation of a filter expression (described later).</t> | |||
</dd> | </dd> | |||
<dt>Children (of a node):</dt> | <dt>Children (of a node):</dt> | |||
<dd> | <dd> | |||
<t>If the node is an array, the nodes of its elements. | <t>If the node is an array, the nodes of its elements; if the node i | |||
If the node is an object, the nodes of its member values. | s an object, the nodes of its member values. | |||
If the node is neither an array nor an object, it has no children.</t> | If the node is neither an array nor an object, it has no children.</t> | |||
</dd> | </dd> | |||
<dt>Descendants (of a node):</dt> | <dt>Descendants (of a node):</dt> | |||
<dd> | <dd> | |||
<t>The children of the node, together with the children of its child ren, and so forth | <t>The children of the node, together with the children of its child ren, and so forth | |||
recursively. More formally, the "descendants" relation between nodes is the tran sitive | recursively. More formally, the "descendants" relation between nodes is the tran sitive | |||
closure of the "children" relation.</t> | closure of the "children" relation.</t> | |||
</dd> | </dd> | |||
<dt>Depth (of a descendant node within a value):</dt> | <dt>Depth (of a descendant node within a value):</dt> | |||
<dd> | <dd> | |||
<t>The number of ancestors of the node within the value. The root no de of the value has depth zero, | <t>The number of ancestors of the node within the value. The root no de of the value has depth zero, | |||
the children of the root node have depth one, their children have depth two, and so forth.</t> | the children of the root node have depth one, their children have depth two, and so forth.</t> | |||
</dd> | </dd> | |||
<dt>Nodelist:</dt> | <dt>Nodelist:</dt> | |||
<dd> | <dd> | |||
<t>A list of nodes. | <t>A list of nodes. | |||
While a nodelist can be represented in JSON, e.g. as an array, this document | While a nodelist can be represented in JSON, e.g., as an array, this document | |||
does not require or assume any particular representation.</t> | does not require or assume any particular representation.</t> | |||
</dd> | </dd> | |||
<dt>Parameter:</dt> | <dt>Parameter:</dt> | |||
<dd> | <dd> | |||
<t>Formal parameter (of a function) that can take a function argumen t | <t>Formal parameter (of a function) that can take a function argumen t | |||
(an actual parameter) in a function-expression.</t> | (an actual parameter) in a function expression.</t> | |||
</dd> | </dd> | |||
<dt>Normalized Path:</dt> | <dt>Normalized Path:</dt> | |||
<dd> | <dd> | |||
<t>A form of JSONPath expression that identifies a node in a value b y | <t>A form of JSONPath expression that identifies a node in a value b y | |||
providing a query that results in exactly that node. Each node in a | providing a query that results in exactly that node. Each node in a | |||
query argument is identified by exactly one Normalized Path (we say, the | query argument is identified by exactly one Normalized Path (we say that the | |||
Normalized Path is "unique" for that node), and, to be a Normalized | Normalized Path is "unique" for that node), and to be a Normalized | |||
Path for a specific query argument, the Normalized Path needs to identify | Path for a specific query argument, the Normalized Path needs to identify | |||
exactly one node. Similar | exactly one node. This is similar | |||
to, but syntactically different from, a JSON Pointer <xref target="RFC6901"/>. | to, but syntactically different from, a JSON Pointer <xref target="RFC6901"/>. | |||
Note: This definition is based on the syntactical definition in <xref target="no rmalized-paths"/>; | Note: This definition is based on the syntactical definition in <xref target="no rmalized-paths"/>; | |||
JSONPath expressions that identify a node in a value but do not conform to that | JSONPath expressions that identify a node in a value but do not conform to that | |||
syntax are not Normalized Paths.</t> | syntax are not Normalized Paths.</t> | |||
</dd> | </dd> | |||
<dt>Unicode Scalar Value:</dt> | <dt>Unicode Scalar Value:</dt> | |||
<dd> | <dd> | |||
<t>Any Unicode <xref target="UNICODE"/> code point except high-surro | <t>Any Unicode <xref target="UNICODE"/> code point except high-surro | |||
gate and low-surrogate code points. | gate and low-surrogate code points (in other words, integers in the inclusive ba | |||
In other words, integers in either of the inclusive base 16 ranges 0 to D7FF and | se 16 ranges, either 0 to D7FF or | |||
E000 to 10FFFF. JSONPath queries are sequences of Unicode scalar values.</t> | E000 to 10FFFF). JSONPath queries are sequences of Unicode scalar values.</t> | |||
</dd> | </dd> | |||
<dt>Segment:</dt> | <dt>Segment:</dt> | |||
<dd> | <dd> | |||
<t>One of the constructs which select children (<tt>[<selectors&g | <t>One of the constructs that selects children (<tt>[<selectors&g | |||
t;]</tt>) | t;]</tt>) | |||
or descendants (<tt>..[<selectors>]</tt>) of an input value.</t> | or descendants (<tt>..&wj;[<selectors>]</tt>) of an input value.</t> | |||
</dd> | </dd> | |||
<dt>Selector:</dt> | <dt>Selector:</dt> | |||
<dd> | <dd> | |||
<t>A single item within a segment that takes the input value and pro duces a nodelist | <t>A single item within a segment that takes the input value and pro duces a nodelist | |||
consisting of child nodes of the input value.</t> | consisting of child nodes of the input value.</t> | |||
</dd> | </dd> | |||
<dt>Singular Query:</dt> | <dt>Singular Query:</dt> | |||
<dd> | <dd> | |||
<t>A JSONPath expression built from segments that have been syntacti cally restricted in | <t>A JSONPath expression built from segments that have been syntacti cally restricted in | |||
a certain way (<xref target="filter-selector-syntax"/>) so that, regardless of t he input | a certain way (<xref target="filter-selector-syntax"/>) so that, regardless of t he input | |||
value, the expression produces a nodelist containing at most one node. | value, the expression produces a nodelist containing at most one node. | |||
Note: JSONPath expressions that always produce a singular nodelist but do not | Note: JSONPath expressions that always produce a singular nodelist but do not | |||
conform to the syntax in <xref target="filter-selector-syntax"/> are not Singula r Queries.</t> | conform to the syntax in <xref target="filter-selector-syntax"/> are not singula r queries.</t> | |||
</dd> | </dd> | |||
</dl> | </dl> | |||
<section anchor="json-values-as-trees-of-nodes"> | <section anchor="json-values-as-trees-of-nodes"> | |||
<name>JSON Values as Trees of Nodes</name> | <name>JSON Values as Trees of Nodes</name> | |||
<t>This document models the query argument as a tree of JSON values, e ach | <t>This document models the query argument as a tree of JSON values, e ach | |||
with its own node. | with its own node. | |||
A node is either the root node or one of its descendants.</t> | A node is either the root node or one of its descendants.</t> | |||
<t>This document models the result of applying a query to the | <t>This document models the result of applying a query to the | |||
query argument as a nodelist (a list of nodes).</t> | query argument as a nodelist (a list of nodes).</t> | |||
<t>Nodes are the selectable parts of the query argument. | <t>Nodes are the selectable parts of the query argument. | |||
The only parts of an object that can be selected by a query are the | The only parts of an object that can be selected by a query are the | |||
member values. Member names and members (name/value pairs) cannot be | member values. Member names and members (name/value pairs) cannot be | |||
selected. | selected. | |||
Thus, member values have nodes, but members and member names do not. | Thus, member values have nodes, but members and member names do not. | |||
Similarly, member values are children of an object, but members and | Similarly, member values are children of an object, but members and | |||
member names are not.</t> | member names are not.</t> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="history"> | <section anchor="history"> | |||
<name>History</name> | <name>History</name> | |||
<t>This document is based on <contact fullname="Stefan Gössner"/>'s popu | <t>This document is based on <contact fullname="Stefan Gössner"/>'s popu | |||
lar JSONPath proposal | lar JSONPath proposal (dated 2007-02-21) <xref target="JSONPath-orig"/>, builds | |||
dated 2007-02-21 <xref target="JSONPath-orig"/>, builds on the experience from t | on the experience from the widespread | |||
he widespread | ||||
deployment of its implementations, and provides a normative specification for it .</t> | deployment of its implementations, and provides a normative specification for it .</t> | |||
<t><xref target="inspired-by-xpath"/> describes how JSONPath was inspire d by XML's XPath | <t><xref target="inspired-by-xpath"/> describes how JSONPath was inspire d by XML's XPath | |||
<xref target="XPath"/>.</t> | <xref target="XPath"/>.</t> | |||
<t>JSONPath was intended as a light-weight companion to JSON | <t>JSONPath was intended as a lightweight companion to JSON | |||
implementations in programming languages such as PHP and JavaScript, | implementations in programming languages such as PHP and JavaScript, | |||
so instead of defining its own expression language, like XPath did, | so instead of defining its own expression language, like XPath did, | |||
JSONPath delegated parts of a query to the underlying | JSONPath delegated parts of a query to the underlying | |||
runtime, e.g., JavaScript's <tt>eval()</tt> function. | runtime, e.g., JavaScript's <tt>eval()</tt> function. | |||
As JSONPath was implemented in more environments, JSONPath | As JSONPath was implemented in more environments, JSONPath | |||
expressions became decreasingly portable. | expressions became decreasingly portable. | |||
For example, regular expression processing was often delegated to a | For example, regular expression processing was often delegated to a | |||
convenient regular expression engine.</t> | convenient regular expression engine.</t> | |||
<t>This document aims to remove such implementation-specific dependencie s and | <t>This document aims to remove such implementation-specific dependencie s and | |||
serve as a common JSONPath specification that can be used across | serve as a common JSONPath specification that can be used across | |||
skipping to change at line 308 ¶ | skipping to change at line 283 ¶ | |||
<t>The JSON value a JSONPath query is applied to is, by definition, a | <t>The JSON value a JSONPath query is applied to is, by definition, a | |||
valid JSON value. A JSON value is often constructed by parsing | valid JSON value. A JSON value is often constructed by parsing | |||
a JSON text.</t> | a JSON text.</t> | |||
<t>The parsing of a JSON text into a JSON value and what happens if a JS ON | <t>The parsing of a JSON text into a JSON value and what happens if a JS ON | |||
text does not represent valid JSON are not defined by this document. | text does not represent valid JSON are not defined by this document. | |||
Sections <xref target="RFC8259" section="4" sectionFormat="bare"/> and <xref tar get="RFC8259" section="8" sectionFormat="bare"/> of <xref target="RFC8259"/> ide ntify specific situations that may | Sections <xref target="RFC8259" section="4" sectionFormat="bare"/> and <xref tar get="RFC8259" section="8" sectionFormat="bare"/> of <xref target="RFC8259"/> ide ntify specific situations that may | |||
conform to the grammar for JSON texts but are not interoperable uses | conform to the grammar for JSON texts but are not interoperable uses | |||
of JSON, as they may cause unpredictable behavior. | of JSON, as they may cause unpredictable behavior. | |||
This document does not attempt to define predictable | This document does not attempt to define predictable | |||
behavior for JSONPath queries in these situations.</t> | behavior for JSONPath queries in these situations.</t> | |||
<t>Specifically, the "Semantics" subsections of Sections | <t>Specifically, the "Semantics" subsections of Sections | |||
<xref format="counter" target="name-selector"/>, <xref format="counter" target=" wildcard-selector"/>, | <xref format="counter" target="name-selector"/>, <xref format="counter" target=" wildcard-selector"/>, | |||
<xref format="counter" target="filter-selector"/>, and <xref format="counter" ta rget="descendant-segment"/> describe behavior that | <xref format="counter" target="filter-selector"/>, and <xref format="counter" ta rget="descendant-segment"/> describe behavior that | |||
becomes unpredictable when the JSON value for one of the objects | becomes unpredictable when the JSON value for one of the objects | |||
under consideration was constructed out of JSON text that exhibits | under consideration was constructed out of JSON text that exhibits | |||
multiple members for a single object that share the same member name | multiple members for a single object that share the same member name | |||
("duplicate names", see <xref section="4" sectionFormat="of" target="RFC8259"/>) | ("duplicate names"; see <xref section="4" sectionFormat="of" target="RFC8259"/>) | |||
. | . | |||
Also, selecting a child by name (<xref target="name-selector"/>) and comparing s | Also, when selecting a child by name (<xref target="name-selector"/>) and compar | |||
trings | ing strings | |||
(<xref target="comparisons"/> in <xref target="filter-selector"/>) assume these | (<xref target="comparisons"/>), it is assumed these | |||
strings are sequences of Unicode scalar values, becoming unpredictable | strings are sequences of Unicode scalar values; the behavior becomes unpredictab | |||
le | ||||
if they are not (<xref section="8.2" sectionFormat="of" target="RFC8259"/>).</t> | if they are not (<xref section="8.2" sectionFormat="of" target="RFC8259"/>).</t> | |||
</section> | </section> | |||
<section anchor="overview"> | <section anchor="overview"> | |||
<name>Overview of JSONPath Expressions</name> | <name>Overview of JSONPath Expressions</name> | |||
<t>A JSONPath expression is applied to a JSON value, known as the query argument. | <t>A JSONPath expression is applied to a JSON value, known as the query argument. | |||
The output is a nodelist.</t> | The output is a nodelist.</t> | |||
<t>A JSONPath expression consists of an identifier followed by a series | <t>A JSONPath expression consists of an identifier followed by a series | |||
of zero or more segments each of which contains one or more selectors.</t> | of zero or more segments, each of which contains one or more selectors.</t> | |||
<section anchor="ids"> | <section anchor="ids"> | |||
<name>Identifiers</name> | <name>Identifiers</name> | |||
<t>The root node identifier <tt>$</tt> refers to the root node of the query argument, | <t>The root node identifier <tt>$</tt> refers to the root node of the query argument, | |||
i.e., to the argument as a whole.</t> | i.e., to the argument as a whole.</t> | |||
<t>The current node identifier <tt>@</tt> refers to the current node i n the context | <t>The current node identifier <tt>@</tt> refers to the current node i n the context | |||
of the evaluation of a filter expression (<xref target="filter-selector"/>).</t> | of the evaluation of a filter expression (<xref target="filter-selector"/>).</t> | |||
</section> | </section> | |||
<section anchor="segments"> | <section anchor="segments"> | |||
<name>Segments</name> | <name>Segments</name> | |||
<t>Segments select children (<tt>[<selectors>]</tt>) or descenda nts (<tt>..[<selectors>]</tt>) of an input value.</t> | <t>Segments select children (<tt>[<selectors>]</tt>) or descenda nts (<tt>..&wj;[<selectors>]</tt>) of an input value.</t> | |||
<t>Segments can use <em>bracket notation</em>, for example:</t> | <t>Segments can use <em>bracket notation</em>, for example:</t> | |||
<sourcecode type="JSONPath"><![CDATA[ | <sourcecode type="application/jsonpath"><![CDATA[ | |||
$['store']['book'][0]['title'] | $['store']['book'][0]['title'] | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t>or the more compact <em>dot notation</em>, for example:</t> | <t>or the more compact <em>dot notation</em>, for example:</t> | |||
<sourcecode type="JSONPath"><![CDATA[ | <sourcecode type="application/jsonpath"><![CDATA[ | |||
$.store.book[0].title | $.store.book[0].title | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t>Bracket notation contains a comma separated list of one or more sel ectors of any kind. | <t>Bracket notation contains one or more (comma-separated) selectors o f any kind. | |||
Selectors are detailed in the next section.</t> | Selectors are detailed in the next section.</t> | |||
<t>A JSONPath expression may use a combination of bracket and dot nota tions.</t> | <t>A JSONPath expression may use a combination of bracket and dot nota tions.</t> | |||
<t>This document treats the bracket notations as canonical and defines the shorthand dot notation in terms | <t>This document treats the bracket notations as canonical and defines the shorthand dot notation in terms | |||
of bracket notation. Examples and descriptions use shorthands where convenient.< /t> | of bracket notation. Examples and descriptions use shorthand where convenient.</ t> | |||
</section> | </section> | |||
<section anchor="selectors"> | <section anchor="selectors"> | |||
<name>Selectors</name> | <name>Selectors</name> | |||
<t>A name selector, e.g. <tt>'name'</tt>, selects a named child of an | <t>A name selector, e.g., <tt>'name'</tt>, selects a named child of an | |||
object.</t> | object.</t> | |||
<t>An index selector, e.g. <tt>3</tt>, selects an indexed child of an | <t>An index selector, e.g., <tt>3</tt>, selects an indexed child of an | |||
array.</t> | array.</t> | |||
<t>A wildcard <tt>*</tt> (<xref target="wildcard-selector"/>) in the e | <t>In the expression <tt>[*]</tt>, a wildcard <tt>*</tt> (<xref target | |||
xpression <tt>[*]</tt> selects all children of a | ="wildcard-selector"/>) selects all children of a | |||
node and in the expression <tt>..[*]</tt> selects all descendants of a node.</t> | node, and in the expression <tt>..[*]</tt>, it selects all descendants of a node | |||
.</t> | ||||
<t>An array slice <tt>start:end:step</tt> (<xref target="slice"/>) sel ects a series of | <t>An array slice <tt>start:end:step</tt> (<xref target="slice"/>) sel ects a series of | |||
elements from an array, giving a start position, an end position, and | elements from an array, giving a start position, an end position, and | |||
an optional step value that moves the position from the start to the | an optional step value that moves the position from the start to the | |||
end.</t> | end.</t> | |||
<t>Filter expressions <tt>?<logical-expr></tt> select certain ch | <t>A filter expression <tt>?<logical-expr></tt> selects certain | |||
ildren of an object or array, as in:</t> | children of an object or array, as in:</t> | |||
<sourcecode type="JSONPath"><![CDATA[ | <sourcecode type="application/jsonpath"><![CDATA[ | |||
$.store.book[?@.price < 10].title | $.store.book[?@.price < 10].title | |||
]]></sourcecode> | ]]></sourcecode> | |||
</section> | </section> | |||
<section anchor="summary"> | <section anchor="summary"> | |||
<name>Summary</name> | <name>Summary</name> | |||
<t><xref target="tbl-overview"/> provides a brief overview of JSONPath syntax.</t> | <t><xref target="tbl-overview"/> provides a brief overview of JSONPath syntax.</t> | |||
<table anchor="tbl-overview"> | <table anchor="tbl-overview"> | |||
<name>Overview of JSONPath syntax</name> | <name>Overview of JSONPath Syntax</name> | |||
<thead> | <thead> | |||
<tr> | <tr> | |||
<th align="left">Syntax Element</th> | <th align="left">Syntax Element</th> | |||
<th align="left">Description</th> | <th align="left">Description</th> | |||
</tr> | </tr> | |||
</thead> | </thead> | |||
<tbody> | <tbody> | |||
<tr> | <tr> | |||
<td align="left"> | <td align="left"> | |||
<tt>$</tt></td> | <tt>$</tt></td> | |||
skipping to change at line 393 ¶ | skipping to change at line 368 ¶ | |||
<tr> | <tr> | |||
<td align="left"> | <td align="left"> | |||
<tt>@</tt></td> | <tt>@</tt></td> | |||
<td align="left"> | <td align="left"> | |||
<xref target="filter-selector">current node identifier</xref> (valid only within filter selectors)</td> | <xref target="filter-selector">current node identifier</xref> (valid only within filter selectors)</td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="left"> | <td align="left"> | |||
<tt>[<selectors>]</tt></td> | <tt>[<selectors>]</tt></td> | |||
<td align="left"> | <td align="left"> | |||
<xref target="child-segment">child segment</xref> selects zero or more children of a node; contains one or more selectors, separated by commas </td> | <xref target="child-segment">child segment</xref>: selects zer o or more children of a node</td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="left"> | <td align="left"> | |||
<tt>.name</tt></td> | <tt>.name</tt></td> | |||
<td align="left">shorthand for <tt>['name']</tt></td> | <td align="left">shorthand for <tt>['name']</tt></td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="left"> | <td align="left"> | |||
<tt>.*</tt></td> | <tt>.*</tt></td> | |||
<td align="left">shorthand for <tt>[*]</tt></td> | <td align="left">shorthand for <tt>[*]</tt></td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="left"> | <td align="left"> | |||
<tt>..[<selectors>]</tt></td> | <tt>..&wj;[<selectors>]</tt></td> | |||
<td align="left"> | <td align="left"> | |||
<xref target="descendant-segment">descendant segment</xref>: s elects zero or more descendants of a node; contains one or more selectors, separ ated by commas</td> | <xref target="descendant-segment">descendant segment</xref>: s elects zero or more descendants of a node</td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="left"> | <td align="left"> | |||
<tt>..name</tt></td> | <tt>..name</tt></td> | |||
<td align="left">shorthand for <tt>..['name']</tt></td> | <td align="left">shorthand for <tt>..['name']</tt></td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="left"> | <td align="left"> | |||
<tt>..*</tt></td> | <tt>..*</tt></td> | |||
<td align="left">shorthand for <tt>..[*]</tt></td> | <td align="left">shorthand for <tt>..[*]</tt></td> | |||
skipping to change at line 431 ¶ | skipping to change at line 406 ¶ | |||
<tr> | <tr> | |||
<td align="left"> | <td align="left"> | |||
<tt>'name'</tt></td> | <tt>'name'</tt></td> | |||
<td align="left"> | <td align="left"> | |||
<xref target="name-selector">name selector</xref>: selects a n amed child of an object</td> | <xref target="name-selector">name selector</xref>: selects a n amed child of an object</td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="left"> | <td align="left"> | |||
<tt>*</tt></td> | <tt>*</tt></td> | |||
<td align="left"> | <td align="left"> | |||
<xref target="name-selector">wildcard selector</xref>: selects all children of a node</td> | <xref target="wildcard-selector">wildcard selector</xref>: sel ects all children of a node</td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="left"> | <td align="left"> | |||
<tt>3</tt></td> | <tt>3</tt></td> | |||
<td align="left"> | <td align="left"> | |||
<xref target="index-selector">index selector</xref>: selects a n indexed child of an array (from 0)</td> | <xref target="index-selector">index selector</xref>: selects a n indexed child of an array (from 0)</td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="left"> | <td align="left"> | |||
<tt>0:100:5</tt></td> | <tt>0:100:5</tt></td> | |||
skipping to change at line 465 ¶ | skipping to change at line 440 ¶ | |||
<xref target="fnex">function extension</xref>: invokes a funct ion in a filter expression</td> | <xref target="fnex">function extension</xref>: invokes a funct ion in a filter expression</td> | |||
</tr> | </tr> | |||
</tbody> | </tbody> | |||
</table> | </table> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="jsonpath-examples"> | <section anchor="jsonpath-examples"> | |||
<name>JSONPath Examples</name> | <name>JSONPath Examples</name> | |||
<t>This section is informative. It provides examples of JSONPath express ions.</t> | <t>This section is informative. It provides examples of JSONPath express ions.</t> | |||
<t>The examples are based on the simple JSON value shown in | <t>The examples are based on the simple JSON value shown in | |||
<xref target="fig-example-value"/>, representing a bookstore (that also has a bi cycle).</t> | <xref target="fig-example-value"/>, representing a bookstore (which also has a b icycle).</t> | |||
<figure anchor="fig-example-value"> | <figure anchor="fig-example-value"> | |||
<name>Example JSON value</name> | <name>Example JSON Value</name> | |||
<sourcecode type="json"><![CDATA[ | <sourcecode type="json"><![CDATA[ | |||
{ "store": { | { "store": { | |||
"book": [ | "book": [ | |||
{ "category": "reference", | { "category": "reference", | |||
"author": "Nigel Rees", | "author": "Nigel Rees", | |||
"title": "Sayings of the Century", | "title": "Sayings of the Century", | |||
"price": 8.95 | "price": 8.95 | |||
}, | }, | |||
{ "category": "fiction", | { "category": "fiction", | |||
"author": "Evelyn Waugh", | "author": "Evelyn Waugh", | |||
skipping to change at line 504 ¶ | skipping to change at line 479 ¶ | |||
"bicycle": { | "bicycle": { | |||
"color": "red", | "color": "red", | |||
"price": 399 | "price": 399 | |||
} | } | |||
} | } | |||
} | } | |||
]]></sourcecode> | ]]></sourcecode> | |||
</figure> | </figure> | |||
<t><xref target="tbl-example"/> shows some JSONPath queries that might b e applied to this example and their intended results.</t> | <t><xref target="tbl-example"/> shows some JSONPath queries that might b e applied to this example and their intended results.</t> | |||
<table anchor="tbl-example"> | <table anchor="tbl-example"> | |||
<name>Example JSONPath expressions and their intended results when app lied to the example JSON value</name> | <name>Example JSONPath Expressions and Their Intended Results When App lied to the Example JSON Value</name> | |||
<thead> | <thead> | |||
<tr> | <tr> | |||
<th align="left">JSONPath</th> | <th align="left">JSONPath</th> | |||
<th align="left">Intended result</th> | <th align="left">Intended Result</th> | |||
</tr> | </tr> | |||
</thead> | </thead> | |||
<tbody> | <tbody> | |||
<tr> | <tr> | |||
<td align="left"> | <td align="left"> | |||
<tt>$.store.book[*].author</tt></td> | <tt>$.store.book[*].author</tt></td> | |||
<td align="left">the authors of all books in the store</td> | <td align="left">the authors of all books in the store</td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="left"> | <td align="left"> | |||
<tt>$..author</tt></td> | <tt>$..author</tt></td> | |||
<td align="left">all authors</td> | <td align="left">all authors</td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="left"> | <td align="left"> | |||
<tt>$.store.*</tt></td> | <tt>$.store.*</tt></td> | |||
<td align="left">all things in store, which are some books and a r ed bicycle</td> | <td align="left">all things in the store, which are some books and a red bicycle</td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="left"> | <td align="left"> | |||
<tt>$.store..price</tt></td> | <tt>$.store..price</tt></td> | |||
<td align="left">the prices of everything in the store</td> | <td align="left">the prices of everything in the store</td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="left"> | <td align="left"> | |||
<tt>$..book[2]</tt></td> | <tt>$..book[2]</tt></td> | |||
<td align="left">the third book</td> | <td align="left">the third book</td> | |||
skipping to change at line 580 ¶ | skipping to change at line 555 ¶ | |||
<td align="left">all member values and array elements contained in the input value</td> | <td align="left">all member values and array elements contained in the input value</td> | |||
</tr> | </tr> | |||
</tbody> | </tbody> | |||
</table> | </table> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="jsonpath-syntax-and-semantics"> | <section anchor="jsonpath-syntax-and-semantics"> | |||
<name>JSONPath Syntax and Semantics</name> | <name>JSONPath Syntax and Semantics</name> | |||
<section anchor="synsem-overview"> | <section anchor="synsem-overview"> | |||
<name>Overview</name> | <name>Overview</name> | |||
<t>A JSONPath <em>expression</em> is a string which, when applied to a J | <t>A JSONPath <em>expression</em> is a string that, when applied to a JS | |||
SON value, | ON value | |||
the <em>query argument</em>, selects zero or more nodes of the argument and outp | (the <em>query argument</em>), selects zero or more nodes of the argument and ou | |||
uts | tputs | |||
these nodes as a nodelist.</t> | these nodes as a nodelist.</t> | |||
<t>A query <bcp14>MUST</bcp14> be encoded using UTF-8. | <t>A query <bcp14>MUST</bcp14> be encoded using UTF-8. | |||
The grammar for queries given in this document assumes that its UTF-8 form is fi rst decoded into | The grammar for queries given in this document assumes that its UTF-8 form is fi rst decoded into | |||
Unicode scalar values as described | Unicode scalar values as described | |||
in <xref target="RFC3629"/>; implementation approaches that lead to an equivalen t | in <xref target="RFC3629"/>; implementation approaches that lead to an equivalen t | |||
result are possible.</t> | result are possible.</t> | |||
<t>A string to be used as a JSONPath query needs to be <em>well-formed</ | ||||
em> and | <t>A string to be used as a JSONPath query needs to be <em>well-formed</em> and | |||
<em>valid</em>. | <em>valid</em>. | |||
A string is a well-formed JSONPath query if it conforms to the ABNF syntax in th is document. | A string is a well-formed JSONPath query if it conforms to the ABNF syntax in th is document. | |||
A well-formed JSONPath query is valid if it also fulfills all semantic | A well-formed JSONPath query is valid if it also fulfills both semantic | |||
requirements posed by this document, which are:</t> | requirements posed by this document, which are as follows:</t> | |||
<ol spacing="normal" type="1"><li>Integer numbers in the JSONPath query that are relevant | <ol spacing="normal" type="1"><li>Integer numbers in the JSONPath query that are relevant | |||
to the JSONPath processing (e.g., index values and steps) <bcp14>MUST</bcp14> be | to the JSONPath processing (e.g., index values and steps) <bcp14>MUST</bcp14> be | |||
within the range of exact integer values defined in I-JSON (see <xref section="2 | within the range of exact integer values defined in Internet JSON (I-JSON) (see | |||
.2" sectionFormat="of" target="RFC7493"/>), namely within the interval [−(2<sup> | <xref section="2.2" sectionFormat="of" target="RFC7493"/>), namely within the in | |||
53</sup>)+1, | terval [-(2<sup>53</sup>)+1, | |||
(2<sup>53</sup>)−1].</li> | (2<sup>53</sup>)-1].</li> | |||
<li>Uses of function extensions <bcp14>MUST</bcp14> be <em>well-typed< /em>, | <li>Uses of function extensions <bcp14>MUST</bcp14> be <em>well-typed< /em>, | |||
as described in <xref target="fnex"/>.</li> | as described in <xref target="well-typedness"/>.</li> | |||
</ol> | </ol> | |||
<t>A JSONPath implementation <bcp14>MUST</bcp14> raise an error for any query which is not | <t>A JSONPath implementation <bcp14>MUST</bcp14> raise an error for any query that is not | |||
well-formed and valid. | well-formed and valid. | |||
The well-formedness and the validity of JSONPath queries are independent of | The well-formedness and the validity of JSONPath queries are independent of | |||
the JSON value the query is applied to. No further errors relating to the | the JSON value the query is applied to. No further errors relating to the | |||
well-formedness and the validity of a JSONPath query can be | well-formedness and the validity of a JSONPath query can be | |||
raised during application of the query to a value. | raised during application of the query to a value. | |||
This clearly separates well-formedness/validity errors in the query | This clearly separates well-formedness/validity errors in the query | |||
from mismatches that may actually stem from flaws in the data.</t> | from mismatches that may actually stem from flaws in the data.</t> | |||
<t>Mismatches between the structure expected by a valid query | <t>Mismatches between the structure expected by a valid query | |||
and the structure found in the data can lead to empty query results, | and the structure found in the data can lead to empty query results, | |||
which may be unexpected and indicate bugs in either. | which may be unexpected and indicate bugs in either. | |||
JSONPath implementations might therefore want to provide diagnostics | JSONPath implementations might therefore want to provide diagnostics | |||
to the application developer that aid in finding the cause of empty | to the application developer that aid in finding the cause of empty | |||
results.</t> | results.</t> | |||
<t>Obviously, an implementation can still fail when executing a JSONPath | <t>Obviously, an implementation can still fail when executing a JSONPath | |||
query, e.g., because of resource depletion, but this is not modeled in | query, e.g., because of resource depletion, but this is not modeled in | |||
this document. However, the implementation <bcp14>MUST NOT</bcp14> | this document. However, the implementation <bcp14>MUST NOT</bcp14> | |||
silently malfunction. Specifically, if a valid JSONPath query is | silently malfunction. Specifically, if a valid JSONPath query is | |||
evaluated against a structured value whose size is too large to | evaluated against a structured value whose size is too large to | |||
process the query correctly (for instance requiring the processing of | process the query correctly (for instance, requiring the processing of | |||
numbers that fall outside the range of exact values), the implementation | numbers that fall outside the range of exact values), the implementation | |||
<bcp14>MUST</bcp14> provide an indication of overflow.</t> | <bcp14>MUST</bcp14> provide an indication of overflow.</t> | |||
<t>(Readers familiar with the HTTP error model may be reminded of 400 | <t>(Readers familiar with the HTTP error model may be reminded of 400 | |||
type errors when pondering well-formedness and validity, while | type errors when pondering well-formedness and validity, and they may | |||
resource depletion and related errors are comparable to 500 type | recognize resource depletion and related errors as comparable to 500 type | |||
errors.)</t> | errors.)</t> | |||
<section anchor="syntax"> | <section anchor="syntax"> | |||
<name>Syntax</name> | <name>Syntax</name> | |||
<t>Syntactically, a JSONPath query consists of a root identifier (<tt> $</tt>), which | <t>Syntactically, a JSONPath query consists of a root identifier (<tt> $</tt>), which | |||
stands for a nodelist that contains the root node of the query argument, | stands for a nodelist that contains the root node of the query argument, | |||
followed by a possibly empty sequence of <em>segments</em>.</t> | followed by a possibly empty sequence of <em>segments</em>.</t> | |||
<sourcecode type="abnf" name="jsonpath-collected.abnf"><![CDATA[ | <sourcecode type="abnf" name="jsonpath-collected.abnf"><![CDATA[ | |||
jsonpath-query = root-identifier segments | jsonpath-query = root-identifier segments | |||
segments = *(S segment) | segments = *(S segment) | |||
skipping to change at line 648 ¶ | skipping to change at line 624 ¶ | |||
%x0D ; Carriage return | %x0D ; Carriage return | |||
S = *B ; optional blank space | S = *B ; optional blank space | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t>The syntax and semantics of segments are defined in <xref target="s egments-details"/>.</t> | <t>The syntax and semantics of segments are defined in <xref target="s egments-details"/>.</t> | |||
</section> | </section> | |||
<section anchor="semantics"> | <section anchor="semantics"> | |||
<name>Semantics</name> | <name>Semantics</name> | |||
<t>In this document, the semantics of a JSONPath query define the | <t>In this document, the semantics of a JSONPath query define the | |||
required results and do not prescribe the internal workings of an | required results and do not prescribe the internal workings of an | |||
implementation. This document may describe semantics in a procedural | implementation. This document may describe semantics in a procedural | |||
step-by-step fashion, but such descriptions are normative only in the sense that | step-by-step fashion; however, such descriptions are normative only in the sense | |||
any implementation <bcp14>MUST</bcp14> produce an identical result, but not in | that any implementation <bcp14>MUST</bcp14> produce an identical result but not | |||
the sense that implementors are required to use the same algorithms.</t> | in the sense that implementers are required to use the same algorithms.</t> | |||
<t>The semantics are that a valid query is executed against a value, | <t>The semantics are that a valid query is executed against a value | |||
the <em>query argument</em>, and produces a nodelist (i.e., a list of zero or mo | (the <em>query argument</em>) and produces a nodelist (i.e., a list of zero or m | |||
re nodes of the value).</t> | ore nodes of the value).</t> | |||
<t>The query is a root identifier followed by a sequence of zero or mo re segments, each of | <t>The query is a root identifier followed by a sequence of zero or mo re segments, each of | |||
which is applied to the result of the previous root identifier or segment and pr ovides | which is applied to the result of the previous root identifier or segment and pr ovides | |||
input to the next segment. | input to the next segment. | |||
These results and inputs take the form of nodelists.</t> | These results and inputs take the form of nodelists.</t> | |||
<t>The nodelist resulting from the root identifier contains a single n | <t>The nodelist resulting from the root identifier contains a single n | |||
ode, | ode | |||
the query argument. | (the query argument). | |||
The nodelist resulting from the last segment is presented as the | The nodelist resulting from the last segment is presented as the | |||
result of the query. Depending on the specific API, it might be | result of the query. Depending on the specific API, it might be | |||
presented as an array of the JSON values at the nodes, an array of | presented as an array of the JSON values at the nodes, an array of | |||
Normalized Paths referencing the nodes, or both — or some other | Normalized Paths referencing the nodes, or both -- or some other | |||
representation as desired by the implementation. | representation as desired by the implementation. | |||
Note: an empty nodelist is a valid query result.</t> | Note: An empty nodelist is a valid query result.</t> | |||
<t>A segment operates on each of the nodes in its input nodelist in tu rn, | <t>A segment operates on each of the nodes in its input nodelist in tu rn, | |||
and the resultant nodelists are concatenated in the order of the input | and the resultant nodelists are concatenated in the order of the input | |||
nodelist they were derived from to produce | nodelist they were derived from to produce | |||
the result of the segment. A node may be selected more than once and | the result of the segment. A node may be selected more than once and | |||
appears that number of times in the nodelist. Duplicate nodes are not removed.</ t> | appears that number of times in the nodelist. Duplicate nodes are not removed.</ t> | |||
<t>A syntactically valid segment <bcp14>MUST NOT</bcp14> produce error s when executing the query. | <t>A syntactically valid segment <bcp14>MUST NOT</bcp14> produce error s when executing the query. | |||
This means that some | This means that some | |||
operations that might be considered erroneous, such as using an index | operations that might be considered erroneous, such as using an index | |||
lying outside the range of an array, | lying outside the range of an array, | |||
simply result in fewer nodes being selected. | simply result in fewer nodes being selected. | |||
(Additional discussion of this property can be found in the | (Additional discussion of this property can be found in the introduction of <xre | |||
introduction to <xref target="synsem-overview"/>.)</t> | f target="synsem-overview"/>.)</t> | |||
<t>As a consequence of this approach, if any of the segments produces | <t>As a consequence of this approach, if any of the segments | |||
an empty nodelist, | produces an empty nodelist, then the whole query produces an empty | |||
then the whole query produces an empty nodelist.</t> | nodelist. | |||
<t>If a query may produce a nodelist with more than one possible order | </t> | |||
ing, a particular implementation | <t>If the semantics of a query give an implementation a choice of prod | |||
may also produce distinct orderings in successive runs of the query.</t> | ucing multiple possible orderings, a particular implementation | |||
may produce distinct orderings in successive runs of the query.</t> | ||||
</section> | </section> | |||
<section anchor="example"> | <section anchor="example"> | |||
<name>Example</name> | <name>Example</name> | |||
<t>Consider this example. With the query argument <tt>{"a":[{"b":0},{" b":1},{"c":2}]}</tt>, the | <t>Consider this example. With the query argument <tt>{"a":[{"b":0},{" b":1},{"c":2}]}</tt>, the | |||
query <tt>$.a[*].b</tt> selects the following list of nodes: <tt>0</tt>, <tt>1</ | query <tt>$.a[*].b</tt> selects the following list of nodes (denoted here by the | |||
tt> | ir values): <tt>0</tt>, <tt>1</tt>.</t> | |||
(denoted here by their value).</t> | ||||
<t>The query consists of <tt>$</tt> followed by three segments: <tt>.a </tt>, <tt>[*]</tt>, and <tt>.b</tt>.</t> | <t>The query consists of <tt>$</tt> followed by three segments: <tt>.a </tt>, <tt>[*]</tt>, and <tt>.b</tt>.</t> | |||
<t>Firstly, <tt>$</tt> produces a nodelist consisting of just the quer y argument.</t> | <t>First, <tt>$</tt> produces a nodelist consisting of just the query argument.</t> | |||
<t>Next, <tt>.a</tt> selects from any object input node and selects th e | <t>Next, <tt>.a</tt> selects from any object input node and selects th e | |||
node of any | node of any | |||
member value of the input | member value of the input | |||
node corresponding to the member name <tt>"a"</tt>. | node corresponding to the member name <tt>"a"</tt>. | |||
The result is again a list of one node: <tt>[{"b":0},{"b":1},{"c":2}]</tt>.</t> | The result is again a list containing a single node: <tt>[{"b":0},{"b":1},{"c":2 | |||
<t>Next, <tt>[*]</tt> selects from any array input node all its elemen | }]</tt>.</t> | |||
ts | <t>Next, <tt>[*]</tt> selects all the elements | |||
(for an object input node, it would select all its member | from the input array node. | |||
values, but not the member names). | ||||
The result is a list of three nodes: <tt>{"b":0}</tt>, <tt>{"b":1}</tt>, and <tt >{"c":2}</tt>.</t> | The result is a list of three nodes: <tt>{"b":0}</tt>, <tt>{"b":1}</tt>, and <tt >{"c":2}</tt>.</t> | |||
<t>Finally, <tt>.b</tt> selects from any object input node with a memb er name | <t>Finally, <tt>.b</tt> selects from any object input node with a memb er name | |||
<tt>b</tt> and selects the node of the member value of the input node correspond ing to that name. | <tt>b</tt> and selects the node of the member value of the input node correspond ing to that name. | |||
The result is a list containing <tt>0</tt>, <tt>1</tt>. | The result is a list containing <tt>0</tt>, <tt>1</tt>. | |||
This is the concatenation of three lists, two of length one containing | This is the concatenation of three lists: two of length one containing | |||
<tt>0</tt>, <tt>1</tt>, respectively, and one of length zero.</t> | <tt>0</tt>, <tt>1</tt>, respectively, and one of length zero.</t> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="root-identifier"> | <section anchor="root-identifier"> | |||
<name>Root Identifier</name> | <name>Root Identifier</name> | |||
<section anchor="syntax-1"> | <section anchor="syntax-1"> | |||
<name>Syntax</name> | <name>Syntax</name> | |||
<t>Every JSONPath query (except those inside filter expressions, see < xref target="filter-selector"/>) <bcp14>MUST</bcp14> begin with the root identif ier <tt>$</tt>.</t> | <t>Every JSONPath query (except those inside filter expressions; see < xref target="filter-selector"/>) <bcp14>MUST</bcp14> begin with the root identif ier <tt>$</tt>.</t> | |||
<sourcecode type="abnf" name="jsonpath-collected.abnf"><![CDATA[ | <sourcecode type="abnf" name="jsonpath-collected.abnf"><![CDATA[ | |||
root-identifier = "$" | root-identifier = "$" | |||
]]></sourcecode> | ]]></sourcecode> | |||
</section> | </section> | |||
<section anchor="semantics-1"> | <section anchor="semantics-1"> | |||
<name>Semantics</name> | <name>Semantics</name> | |||
<t>The root identifier <tt>$</tt> represents the root node of the quer y argument | <t>The root identifier <tt>$</tt> represents the root node of the quer y argument | |||
and produces a nodelist consisting of that root node.</t> | and produces a nodelist consisting of that root node.</t> | |||
</section> | </section> | |||
<section anchor="examples"> | <section anchor="examples"> | |||
<name>Examples</name> | <name>Examples</name> | |||
<aside> | <aside> | |||
<t>In this and the following examples in Sections <xref format="coun | <t>Note: In this example and the following examples in Sections <xre | |||
ter" target="root-identifier"/> and | f format="counter" target="root-identifier"/> and | |||
<xref format="counter" target="selector-details"/> except for <xref target="tbl- | <xref format="counter" target="selector-details"/>, except for <xref target="tbl | |||
comparison"/>, we will present a | -comparison"/>, we will present a | |||
JSON text to show the JSON value used as the query argument to the | JSON text to show the JSON value used as the query argument to the | |||
queries in the examples, and then a table with the columns:</t> | queries in the examples and then a table with the following columns:</t> | |||
<ul spacing="normal"> | <ul spacing="normal"> | |||
<li>Query: an example query to be applied to the query argument</l i> | <li>Query: an example query to be applied to the query argument</l i> | |||
<li>Result: the query result as a list of JSON values that were lo cated in the query argument</li> | <li>Result: the query result as a list of JSON values that were lo cated in the query argument</li> | |||
<li>Result Path: the query result as a list of (normalized) paths into | <li>Result Path: the query result as a list of (normalized) paths into | |||
the query argument, giving locations of the JSON values in the previous column</ li> | the query argument, giving locations of the JSON values in the previous column</ li> | |||
<li>Comment: descriptive information</li> | <li>Comment: descriptive information</li> | |||
</ul> | </ul> | |||
</aside> | </aside> | |||
<t>JSON:</t> | <t>JSON:</t> | |||
<sourcecode type="json"><![CDATA[ | <sourcecode type="json"><![CDATA[ | |||
{"k": "v"} | {"k": "v"} | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t>Queries:</t> | <t>Queries:</t> | |||
<table anchor="tbl-root"> | <table anchor="tbl-root"> | |||
<name>Root identifier examples</name> | <name>Root Identifier Example</name> | |||
<thead> | <thead> | |||
<tr> | <tr> | |||
<th align="center">Query</th> | <th align="center">Query</th> | |||
<th align="left">Result</th> | <th align="left">Result</th> | |||
<th align="center">Result Path</th> | <th align="center">Result Path</th> | |||
<th align="left">Comment</th> | <th align="left">Comment</th> | |||
</tr> | </tr> | |||
</thead> | </thead> | |||
<tbody> | <tbody> | |||
<tr> | <tr> | |||
skipping to change at line 766 ¶ | skipping to change at line 741 ¶ | |||
</tr> | </tr> | |||
</tbody> | </tbody> | |||
</table> | </table> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="selector-details"> | <section anchor="selector-details"> | |||
<name>Selectors</name> | <name>Selectors</name> | |||
<t>Selectors appear only inside <xref target="child-segment">child segme nts</xref> and | <t>Selectors appear only inside <xref target="child-segment">child segme nts</xref> and | |||
<xref target="descendant-segment">descendant segments</xref>.</t> | <xref target="descendant-segment">descendant segments</xref>.</t> | |||
<t>A selector produces a nodelist consisting of zero or more children of the input value.</t> | <t>A selector produces a nodelist consisting of zero or more children of the input value.</t> | |||
<t>There are various kinds of selectors which produce children of object s, children of arrays, | <t>There are various kinds of selectors that produce children of objects , children of arrays, | |||
or children of either objects or arrays.</t> | or children of either objects or arrays.</t> | |||
<sourcecode type="abnf" name="jsonpath-collected.abnf"><![CDATA[ | <sourcecode type="abnf" name="jsonpath-collected.abnf"><![CDATA[ | |||
selector = name-selector / | selector = name-selector / | |||
wildcard-selector / | wildcard-selector / | |||
slice-selector / | slice-selector / | |||
index-selector / | index-selector / | |||
filter-selector | filter-selector | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t>The syntax and semantics of each kind of selector are defined below.< /t> | <t>The syntax and semantics of each kind of selector are defined below.< /t> | |||
<section anchor="name-selector"> | <section anchor="name-selector"> | |||
<name>Name Selector</name> | <name>Name Selector</name> | |||
<section anchor="syntax-name"> | <section anchor="syntax-name"> | |||
<name>Syntax</name> | <name>Syntax</name> | |||
skipping to change at line 799 ¶ | skipping to change at line 774 ¶ | |||
double-quoted = unescaped / | double-quoted = unescaped / | |||
%x27 / ; ' | %x27 / ; ' | |||
ESC %x22 / ; \" | ESC %x22 / ; \" | |||
ESC escapable | ESC escapable | |||
single-quoted = unescaped / | single-quoted = unescaped / | |||
%x22 / ; " | %x22 / ; " | |||
ESC %x27 / ; \' | ESC %x27 / ; \' | |||
ESC escapable | ESC escapable | |||
ESC = %x5C ; \ backslash | ESC = %x5C ; \ backslash | |||
unescaped = %x20-21 / ; see RFC 8259 | unescaped = %x20-21 / ; see RFC 8259 | |||
; omit 0x22 " | ; omit 0x22 " | |||
%x23-26 / | %x23-26 / | |||
; omit 0x27 ' | ; omit 0x27 ' | |||
%x28-5B / | %x28-5B / | |||
; omit 0x5C \ | ; omit 0x5C \ | |||
%x5D-D7FF / ; skip surrogate code points | %x5D-D7FF / | |||
; skip surrogate code points | ||||
%xE000-10FFFF | %xE000-10FFFF | |||
escapable = %x62 / ; b BS backspace U+0008 | escapable = %x62 / ; b BS backspace U+0008 | |||
%x66 / ; f FF form feed U+000C | %x66 / ; f FF form feed U+000C | |||
%x6E / ; n LF line feed U+000A | %x6E / ; n LF line feed U+000A | |||
%x72 / ; r CR carriage return U+000D | %x72 / ; r CR carriage return U+000D | |||
%x74 / ; t HT horizontal tab U+0009 | %x74 / ; t HT horizontal tab U+0009 | |||
"/" / ; / slash (solidus) U+002F | "/" / ; / slash (solidus) U+002F | |||
"\" / ; \ backslash (reverse solidus) U+005C | "\" / ; \ backslash (reverse solidus) U+005C | |||
(%x75 hexchar) ; uXXXX U+XXXX | (%x75 hexchar) ; uXXXX U+XXXX | |||
hexchar = non-surrogate / | hexchar = non-surrogate / | |||
(high-surrogate "\" %x75 low-surrogate) | (high-surrogate "\" %x75 low-surrogate) | |||
non-surrogate = ((DIGIT / "A"/"B"/"C" / "E"/"F") 3HEXDIG) / | non-surrogate = ((DIGIT / "A"/"B"/"C" / "E"/"F") 3HEXDIG) / | |||
("D" %x30-37 2HEXDIG ) | ("D" %x30-37 2HEXDIG ) | |||
high-surrogate = "D" ("8"/"9"/"A"/"B") 2HEXDIG | high-surrogate = "D" ("8"/"9"/"A"/"B") 2HEXDIG | |||
low-surrogate = "D" ("C"/"D"/"E"/"F") 2HEXDIG | low-surrogate = "D" ("C"/"D"/"E"/"F") 2HEXDIG | |||
HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F" | HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F" | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t>Notes:</t> | <t>Notes:</t> | |||
<ul spacing="normal"> | <ul spacing="normal"> | |||
<li> | <li> | |||
<tt>double-quoted</tt> strings follow the JSON string syntax (<x | <tt>Double-quoted</tt> strings follow the JSON string syntax (<x | |||
ref section="7" sectionFormat="of" target="RFC8259"/>); | ref section="7" sectionFormat="of" target="RFC8259"/>); | |||
<tt>single-quoted</tt> strings follow an analogous pattern (<xref target="syntax | <tt>single-quoted</tt> strings follow an analogous pattern. | |||
-index"/>). | ||||
No attempt was made to improve on this syntax, so if it is desired to | No attempt was made to improve on this syntax, so if it is desired to | |||
escape characters with | escape characters with | |||
scalar values above 0xFFFF, such as <u format="num-lit-name">🤔</u>, | scalar values above 0xFFFF, such as <u format="num-lit-name">🎼</u>, | |||
they need to be represented | they need to be represented | |||
by a pair of surrogate escapes (<tt>"\uD83E\uDD14"</tt> in this case).</li> | by a pair of surrogate escapes (<tt>"\uD83C\uDFBC"</tt> in this case).</li> | |||
<li>Alphabetic characters in ABNF quoted strings are case-insensit | <li>Alphabetic characters in quoted strings are case-insensitive i | |||
ive, | n ABNF, | |||
so each of the hexadecimal digits within <tt>\u</tt> escapes (as specified in ru les | so each of the hexadecimal digits within <tt>\u</tt> escapes (as specified in ru les | |||
referenced by <tt>hexchar</tt>) can be either lower case or upper case, | referenced by <tt>hexchar</tt>) can be either lowercase or uppercase, | |||
while the <tt>u</tt> in <tt>\u</tt> needs to be lower case (indicated as <tt>%x7 | while the <tt>u</tt> in <tt>\u</tt> needs to be lowercase (indicated as <tt>%x75 | |||
5</tt>).</li> | </tt>).</li> | |||
</ul> | </ul> | |||
</section> | </section> | |||
<section anchor="semantics-2"> | <section anchor="semantics-2"> | |||
<name>Semantics</name> | <name>Semantics</name> | |||
<t>A <tt>name-selector</tt> string <bcp14>MUST</bcp14> be converted to a | <t>A <tt>name-selector</tt> string <bcp14>MUST</bcp14> be converted to a | |||
member name <tt>M</tt> by removing the surrounding quotes and | member name <tt>M</tt> by removing the surrounding quotes and | |||
replacing each escape sequence with its equivalent Unicode character, as | replacing each escape sequence with its equivalent Unicode character, as | |||
shown in <xref target="tbl-esc"/>:</t> | shown in <xref target="tbl-esc"/>:</t> | |||
<table anchor="tbl-esc"> | <table anchor="tbl-esc"> | |||
<name>Escape Sequence Replacements</name> | <name>Escape Sequence Replacements</name> | |||
skipping to change at line 923 ¶ | skipping to change at line 899 ¶ | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="center"> | <td align="center"> | |||
<tt>\uXXXX</tt></td> | <tt>\uXXXX</tt></td> | |||
<td align="center">see <xref target="syntax-name"/></td> | <td align="center">see <xref target="syntax-name"/></td> | |||
<td align="left">hexadecimal escape</td> | <td align="left">hexadecimal escape</td> | |||
</tr> | </tr> | |||
</tbody> | </tbody> | |||
</table> | </table> | |||
<t>Applying the <tt>name-selector</tt> to an object node | <t>Applying the <tt>name-selector</tt> to an object node | |||
selects a member value whose name equals the member name <tt>M</tt>, | selects a member value whose name equals the member name <tt>M</tt> | |||
or selects nothing if there is no such member value. | or selects nothing if there is no such member value. | |||
Nothing is selected from a value that is not an object.</t> | Nothing is selected from a value that is not an object.</t> | |||
<t>Note: processing the name selector requires comparing the member name string <tt>M</tt> | <t>Note: Processing the name selector requires comparing the member name string <tt>M</tt> | |||
with member name strings in the JSON to which the selector is being applied. | with member name strings in the JSON to which the selector is being applied. | |||
Two strings <bcp14>MUST</bcp14> be considered equal if and only if they are iden tical | Two strings <bcp14>MUST</bcp14> be considered equal if and only if they are iden tical | |||
sequences of Unicode scalar values. In other words, normalization operations | sequences of Unicode scalar values. In other words, normalization operations | |||
<bcp14>MUST NOT</bcp14> be applied to either the member name string <tt>M</tt> f rom the JSONPath or to | <bcp14>MUST NOT</bcp14> be applied to either the member name string <tt>M</tt> f rom the JSONPath or | |||
the member name strings in the JSON prior to comparison.</t> | the member name strings in the JSON prior to comparison.</t> | |||
</section> | </section> | |||
<section anchor="examples-1"> | <section anchor="examples-1"> | |||
<name>Examples</name> | <name>Examples</name> | |||
<!-- EDITING NOTE: there are non-breaking spaces here between j and | ||||
j --> | ||||
<!-- i.e., j j and not j j --> | ||||
<t>JSON:</t> | <t>JSON:</t> | |||
<sourcecode type="json"><![CDATA[ | <sourcecode type="json"><![CDATA[ | |||
{ | { | |||
"o": {"j j": {"k.k": 3}}, | "o": {"j j": {"k.k": 3}}, | |||
"'": {"@": 2} | "'": {"@": 2} | |||
} | } | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t>Queries:</t> | <t>Queries:</t> | |||
<t>The examples in <xref target="tbl-name"/> show the name selector in use by child segments:</t> | <t>The examples in <xref target="tbl-name"/> show the name selector in use by child segments.</t> | |||
<table anchor="tbl-name"> | <table anchor="tbl-name"> | |||
<name>Name selector examples</name> | <name>Name Selector Examples</name> | |||
<thead> | <thead> | |||
<tr> | <tr> | |||
<th align="center">Query</th> | <th align="center">Query</th> | |||
<th align="left">Result</th> | <th align="left">Result</th> | |||
<th align="center">Result Paths</th> | <th align="center">Result Paths</th> | |||
<th align="left">Comment</th> | <th align="left">Comment</th> | |||
</tr> | </tr> | |||
</thead> | </thead> | |||
<tbody> | <tbody> | |||
<tr> | <tr> | |||
<td align="center"> | <td align="center"> | |||
<tt>$.o['j j']</tt></td> | <tt>$.o['j j']</tt></td> | |||
<td align="left"> | <td align="left"> | |||
<tt>{"k.k": 3}</tt></td> | <tt>{"k.k": 3}</tt></td> | |||
<td align="center"> | <td align="center"> | |||
<tt>$['o']['j j']</tt></td> | <tt>$['o']['j j']</tt></td> | |||
<td align="left">Named value in nested object</td> | <td align="left">Named <br/>value in <br/>a nested <br/>object | |||
</td> | ||||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="center"> | <td align="center"> | |||
<tt>$.o['j j']['k.k']</tt></td> | <tt>$.o['j j']&wj;['k.k']</tt></td> | |||
<td align="left"> | <td align="left"> | |||
<tt>3</tt></td> | <tt>3</tt></td> | |||
<td align="center"> | <td align="center"> | |||
<tt>$['o']['j j']['k.k']</tt></td> | <tt>$['o']['j j']&wj;['k.k']</tt></td> | |||
<td align="left">Nesting further down</td> | <td align="left">Nesting <br/>further <br/>down</td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="center"> | <td align="center"> | |||
<tt>$.o["j j"]["k.k"]</tt></td> | <tt>$.o["j j"]&wj;["k.k"]</tt></td> | |||
<td align="left"> | <td align="left"> | |||
<tt>3</tt></td> | <tt>3</tt></td> | |||
<td align="center"> | <td align="center"> | |||
<tt>$['o']['j j']['k.k']</tt></td> | <tt>$['o']['j j']&wj;['k.k']</tt></td> | |||
<td align="left">Different delimiter in query, unchanged norma | <td align="left">Different <br/>delimiter <br/>in the query, < | |||
lized path</td> | br/>unchanged <br/>Normalized <br/>Path</td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="center"> | <td align="center"> | |||
<tt>$["'"]["@"]</tt></td> | <tt>$["'"]["@"]</tt></td> | |||
<td align="left"> | <td align="left"> | |||
<tt>2</tt></td> | <tt>2</tt></td> | |||
<td align="center"> | <td align="center"> | |||
<tt>$['\'']['@']</tt></td> | <tt>$['\'']['@']</tt></td> | |||
<td align="left">Unusual member names</td> | <td align="left">Unusual <br/>member <br/>names</td> | |||
</tr> | </tr> | |||
</tbody> | </tbody> | |||
</table> | </table> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="wildcard-selector"> | <section anchor="wildcard-selector"> | |||
<name>Wildcard Selector</name> | <name>Wildcard Selector</name> | |||
<section anchor="syntax-2"> | <section anchor="syntax-2"> | |||
<name>Syntax</name> | <name>Syntax</name> | |||
<t>The wildcard selector consists of an asterisk.</t> | <t>The wildcard selector consists of an asterisk.</t> | |||
<sourcecode type="abnf" name="jsonpath-collected.abnf"><![CDATA[ | <sourcecode type="abnf" name="jsonpath-collected.abnf"><![CDATA[ | |||
wildcard-selector = "*" | wildcard-selector = "*" | |||
]]></sourcecode> | ]]></sourcecode> | |||
</section> | </section> | |||
<section anchor="semantics-3"> | <section anchor="semantics-3"> | |||
<name>Semantics</name> | <name>Semantics</name> | |||
<t>A wildcard selector selects the nodes of all children of an objec t or array. | <t>A wildcard selector selects the nodes of all children of an objec t or array. | |||
The order in which the children of an object appear in the resultant nodelist is not stipulated, | The order in which the children of an object appear in the resultant nodelist is not stipulated, | |||
since JSON objects are unordered. | since JSON objects are unordered. | |||
Children of an array appear in array order in the resultant nodelist.</t> | Children of an array appear in array order in the resultant nodelist. | |||
</t> | ||||
<t>Note that the children of an object are its member values, not its | ||||
member names.</t> | ||||
<t>The wildcard selector selects nothing from a primitive JSON value (that is, | <t>The wildcard selector selects nothing from a primitive JSON value (that is, | |||
a number, a string, <tt>true</tt>, <tt>false</tt>, or <tt>null</tt>).</t> | a number, a string, <tt>true</tt>, <tt>false</tt>, or <tt>null</tt>).</t> | |||
</section> | </section> | |||
<section anchor="examples-2"> | <section anchor="examples-2"> | |||
<name>Examples</name> | <name>Examples</name> | |||
<t>JSON:</t> | <t>JSON:</t> | |||
<sourcecode type="json"><![CDATA[ | <sourcecode type="json"><![CDATA[ | |||
{ | { | |||
"o": {"j": 1, "k": 2}, | "o": {"j": 1, "k": 2}, | |||
"a": [5, 3] | "a": [5, 3] | |||
} | } | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t>Queries:</t> | <t>Queries:</t> | |||
<t>The examples in <xref target="tbl-wild"/> show the wildcard selec tor in use by a child segment:</t> | <t>The examples in <xref target="tbl-wild"/> show the wildcard selec tor in use by a child segment.</t> | |||
<table anchor="tbl-wild"> | <table anchor="tbl-wild"> | |||
<name>Wildcard selector examples</name> | <name>Wildcard Selector Examples</name> | |||
<thead> | <thead> | |||
<tr> | <tr> | |||
<th align="center">Query</th> | <th align="center">Query</th> | |||
<th align="left">Result</th> | <th align="left">Result</th> | |||
<th align="center">Result Paths</th> | <th align="center">Result Paths</th> | |||
<th align="left">Comment</th> | <th align="left">Comment</th> | |||
</tr> | </tr> | |||
</thead> | </thead> | |||
<tbody> | <tbody> | |||
<tr> | <tr> | |||
skipping to change at line 1086 ¶ | skipping to change at line 1060 ¶ | |||
<tt>$.a[*]</tt></td> | <tt>$.a[*]</tt></td> | |||
<td align="left"> | <td align="left"> | |||
<tt>5</tt> <br/> <tt>3</tt></td> | <tt>5</tt> <br/> <tt>3</tt></td> | |||
<td align="center"> | <td align="center"> | |||
<tt>$['a'][0]</tt> <br/> <tt>$['a'][1]</tt></td> | <tt>$['a'][0]</tt> <br/> <tt>$['a'][1]</tt></td> | |||
<td align="left">Array members</td> | <td align="left">Array members</td> | |||
</tr> | </tr> | |||
</tbody> | </tbody> | |||
</table> | </table> | |||
<t>The example above with the query <tt>$.o[*, *]</tt> shows that th e wildcard selector may produce nodelists in distinct | <t>The example above with the query <tt>$.o[*, *]</tt> shows that th e wildcard selector may produce nodelists in distinct | |||
orders each time it appears in the child segment, when it is applied to an objec t node with two or more | orders each time it appears in the child segment when it is applied to an object node with two or more | |||
members (but not when it is applied to object nodes with fewer than two members or to array nodes).</t> | members (but not when it is applied to object nodes with fewer than two members or to array nodes).</t> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="index-selector"> | <section anchor="index-selector"> | |||
<name>Index Selector</name> | <name>Index Selector</name> | |||
<section anchor="syntax-index"> | <section anchor="syntax-index"> | |||
<name>Syntax</name> | <name>Syntax</name> | |||
<t>An index selector <tt><index></tt> matches at most one arra y element value.</t> | <t>An index selector <tt><index></tt> matches at most one arra y element value.</t> | |||
<sourcecode type="abnf" name="jsonpath-collected.abnf"><![CDATA[ | <sourcecode type="abnf" name="jsonpath-collected.abnf"><![CDATA[ | |||
index-selector = int ; decimal integer | index-selector = int ; decimal integer | |||
int = "0" / | int = "0" / | |||
(["-"] DIGIT1 *DIGIT) ; - optional | (["-"] DIGIT1 *DIGIT) ; - optional | |||
DIGIT1 = %x31-39 ; 1-9 non-zero digit | DIGIT1 = %x31-39 ; 1-9 non-zero digit | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t>Applying the numerical <tt>index-selector</tt> selects the corres ponding | <t>Applying the numerical <tt>index-selector</tt> selects the corres ponding | |||
element. JSONPath allows it to be negative (see <xref target="index-semantics"/> ).</t> | element. JSONPath allows it to be negative (see <xref target="index-semantics"/> ).</t> | |||
<t>To be valid, the index selector value <bcp14>MUST</bcp14> be in t he I-JSON | <t>To be valid, the index selector value <bcp14>MUST</bcp14> be in t he I-JSON | |||
range of exact values, see <xref target="synsem-overview"/>.</t> | range of exact values (see <xref target="synsem-overview"/>).</t> | |||
<t>Notes:</t> | <t>Notes:</t> | |||
<ul spacing="normal"> | <ul spacing="normal"> | |||
<li>An <tt>index-selector</tt> is an integer (in base 10, as in JS ON numbers).</li> | <li>An <tt>index-selector</tt> is an integer (in base 10, as in JS ON numbers).</li> | |||
<li>As in JSON numbers, the syntax does not allow octal-like integ ers with leading zeros such as <tt>01</tt> or <tt>-01</tt>.</li> | <li>As in JSON numbers, the syntax does not allow octal-like integ ers with leading zeros, such as <tt>01</tt> or <tt>-01</tt>.</li> | |||
</ul> | </ul> | |||
</section> | </section> | |||
<section anchor="index-semantics"> | <section anchor="index-semantics"> | |||
<name>Semantics</name> | <name>Semantics</name> | |||
<t>A non-negative <tt>index-selector</tt> applied to an array select s an array element using a zero-based index. | <t>A non-negative <tt>index-selector</tt> applied to an array select s an array element using a zero-based index. | |||
For example, the selector <tt>0</tt> selects the first and the selector <tt>4</t t> selects the fifth element of a sufficiently long array. | For example, the selector <tt>0</tt> selects the first, and the selector <tt>4</ tt> selects the fifth element of a sufficiently long array. | |||
Nothing is selected, and it is not an error, if the index lies outside the range of the array. Nothing is selected from a value that is not an array.</t> | Nothing is selected, and it is not an error, if the index lies outside the range of the array. Nothing is selected from a value that is not an array.</t> | |||
<t>A negative <tt>index-selector</tt> counts from the array end back wards, | <t>A negative <tt>index-selector</tt> counts from the array end back wards, | |||
obtaining an equivalent non-negative <tt>index-selector</tt> by summing the | obtaining an equivalent non-negative <tt>index-selector</tt> by adding the | |||
length of the array with the negative index. | length of the array to the negative index. | |||
For example, the selector <tt>-1</tt> selects the last and the selector <tt>-2</ | For example, the selector <tt>-1</tt> selects the last, and the selector <tt>-2< | |||
tt> selects the penultimate element of an array with at least two elements. | /tt> selects the penultimate element of an array with at least two elements. | |||
As with non-negative indexes, it is not an error if such an element does | As with non-negative indexes, it is not an error if such an element does | |||
not exist; this simply means that no element is selected.</t> | not exist; this simply means that no element is selected.</t> | |||
</section> | </section> | |||
<section anchor="examples-3"> | <section anchor="examples-3"> | |||
<name>Examples</name> | <name>Examples</name> | |||
<!-- EDITING NOTE: there are non-breaking spaces here between j and | ||||
j --> | ||||
<!-- i.e., j j and not j j --> | ||||
<t>JSON:</t> | <t>JSON:</t> | |||
<sourcecode type="json"><![CDATA[ | <sourcecode type="json"><![CDATA[ | |||
["a","b"] | ["a","b"] | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t>Queries:</t> | <t>Queries:</t> | |||
<t>The examples in <xref target="tbl-index"/> show the index selecto r in use by a child segment.</t> | <t>The examples in <xref target="tbl-index"/> show the index selecto r in use by a child segment.</t> | |||
<table anchor="tbl-index"> | <table anchor="tbl-index"> | |||
<name>Index selector examples</name> | <name>Index Selector Examples</name> | |||
<thead> | <thead> | |||
<tr> | <tr> | |||
<th align="center">Query</th> | <th align="center">Query</th> | |||
<th align="left">Result</th> | <th align="left">Result</th> | |||
<th align="center">Result Paths</th> | <th align="center">Result Paths</th> | |||
<th align="left">Comment</th> | <th align="left">Comment</th> | |||
</tr> | </tr> | |||
</thead> | </thead> | |||
<tbody> | <tbody> | |||
<tr> | <tr> | |||
skipping to change at line 1169 ¶ | skipping to change at line 1140 ¶ | |||
<tt>"a"</tt></td> | <tt>"a"</tt></td> | |||
<td align="center"> | <td align="center"> | |||
<tt>$[0]</tt></td> | <tt>$[0]</tt></td> | |||
<td align="left">Element of array, from the end</td> | <td align="left">Element of array, from the end</td> | |||
</tr> | </tr> | |||
</tbody> | </tbody> | |||
</table> | </table> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="slice"> | <section anchor="slice"> | |||
<name>Array Slice selector</name> | <name>Array Slice Selector</name> | |||
<section anchor="syntax-3"> | <section anchor="syntax-3"> | |||
<name>Syntax</name> | <name>Syntax</name> | |||
<t>The array slice selector has the form <tt><start>:<end&g t;:<step></tt>. | <t>The array slice selector has the form <tt><start>:<end&g t;:<step></tt>. | |||
It matches elements from arrays starting at index <tt><start></tt>, ending | It matches elements from arrays starting at index <tt><start></tt> and end | |||
at — but | ing at (but | |||
not including — <tt><end></tt>, while incrementing by <tt>step</tt> with a | not including) <tt><end></tt>, while incrementing by <tt>step</tt> with a | |||
default of <tt>1</tt>.</t> | default of <tt>1</tt>.</t> | |||
<sourcecode type="abnf" name="jsonpath-collected.abnf"><![CDATA[ | <sourcecode type="abnf" name="jsonpath-collected.abnf"><![CDATA[ | |||
slice-selector = [start S] ":" S [end S] [":" [S step ]] | slice-selector = [start S] ":" S [end S] [":" [S step ]] | |||
start = int ; included in selection | start = int ; included in selection | |||
end = int ; not included in selection | end = int ; not included in selection | |||
step = int ; default: 1 | step = int ; default: 1 | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t>The slice selector consists of three optional decimal integers se parated by colons. | <t>The slice selector consists of three optional decimal integers se parated by colons. | |||
The second colon can be omitted when the third integer is.</t> | The second colon can be omitted when the third integer is omitted.</t> | |||
<t>To be valid, the integers provided <bcp14>MUST</bcp14> be in the I-JSON | <t>To be valid, the integers provided <bcp14>MUST</bcp14> be in the I-JSON | |||
range of exact values, see <xref target="synsem-overview"/>.</t> | range of exact values (see <xref target="synsem-overview"/>).</t> | |||
</section> | </section> | |||
<section anchor="semantics-4"> | <section anchor="semantics-4"> | |||
<name>Semantics</name> | <name>Semantics</name> | |||
<t>The slice selector was inspired by the slice operator of ECMAScri | <t>The slice selector was inspired by | |||
pt | the slice operator that was proposed for ECMAScript 4 (ES4), whic | |||
4 (ES4), which was deprecated in 2014, and that of Python.</t> | h was never released, | |||
and that of Python.</t> | ||||
<section anchor="informal-introduction"> | <section anchor="informal-introduction"> | |||
<name>Informal Introduction</name> | <name>Informal Introduction</name> | |||
<t>This section is informative.</t> | <t>This section is informative.</t> | |||
<t>Array slicing is inspired by the behavior of the <tt>Array.prot otype.slice</tt> method | <t>Array slicing is inspired by the behavior of the <tt>Array.prot otype.slice</tt> method | |||
of the JavaScript language as defined by the ECMA-262 standard <xref target="ECM A-262"/>, | of the JavaScript language, as defined by the ECMA-262 standard <xref target="EC MA-262"/>, | |||
with the addition of the <tt>step</tt> parameter, which is inspired by the Pytho n slice expression.</t> | with the addition of the <tt>step</tt> parameter, which is inspired by the Pytho n slice expression.</t> | |||
<t>The array slice expression <tt>start:end:step</tt> selects elem ents at indices starting at <tt>start</tt>, | <t>The array slice expression <tt>start:end:step</tt> selects elem ents at indices starting at <tt>start</tt>, | |||
incrementing by <tt>step</tt>, and ending with <tt>end</tt> (which is itself exc luded). | incrementing by <tt>step</tt>, and ending with <tt>end</tt> (which is itself exc luded). | |||
So, for example, the expression <tt>1:3</tt> (where <tt>step</tt> defaults to <t t>1</tt>) | So, for example, the expression <tt>1:3</tt> (where <tt>step</tt> defaults to <t t>1</tt>) | |||
selects elements with indices <tt>1</tt> and <tt>2</tt> (in that order) whereas | selects elements with indices <tt>1</tt> and <tt>2</tt> (in that order), whereas | |||
<tt>1:5:2</tt> selects elements with indices <tt>1</tt> and <tt>3</tt>.</t> | <tt>1:5:2</tt> selects elements with indices <tt>1</tt> and <tt>3</tt>.</t> | |||
<t>When <tt>step</tt> is negative, elements are selected in revers e order. Thus, | <t>When <tt>step</tt> is negative, elements are selected in revers e order. Thus, | |||
for example, <tt>5:1:-2</tt> selects elements with indices <tt>5</tt> and <tt>3< | for example, <tt>5:1:-2</tt> selects elements with indices <tt>5</tt> and <tt>3< | |||
/tt>, in | /tt> (in | |||
that order and <tt>::-1</tt> selects all the elements of an array in | that order), and <tt>::-1</tt> selects all the elements of an array in | |||
reverse order.</t> | reverse order.</t> | |||
<t>When <tt>step</tt> is <tt>0</tt>, no elements are selected. | <t>When <tt>step</tt> is <tt>0</tt>, no elements are selected. | |||
(This is the one case that differs from the behavior of Python, which | (This is the one case that differs from the behavior of Python, which | |||
raises an error in this case.)</t> | raises an error in this case.)</t> | |||
<t>The following section specifies the behavior fully, without dep ending on | <t>The following section specifies the behavior fully, without dep ending on | |||
JavaScript or Python behavior.</t> | JavaScript or Python behavior.</t> | |||
</section> | </section> | |||
<section anchor="normative-semantics"> | <section anchor="normative-semantics"> | |||
<name>Normative Semantics</name> | <name>Normative Semantics</name> | |||
<t>A slice expression selects a subset of the elements of the inpu t array, in | <t>A slice expression selects a subset of the elements of the inpu t array in | |||
the same order | the same order | |||
as the array or the reverse order, depending on the sign of the <tt>step</tt> pa rameter. | as the array or the reverse order, depending on the sign of the <tt>step</tt> pa rameter. | |||
It selects no nodes from a node that is not an array.</t> | It selects no nodes from a node that is not an array.</t> | |||
<t>A slice is defined by the two slice parameters, <tt>start</tt> and <tt>end</tt>, and | <t>A slice is defined by the two slice parameters, <tt>start</tt> and <tt>end</tt>, and | |||
an iteration delta, <tt>step</tt>. | an iteration delta, <tt>step</tt>. | |||
Each of these parameters is | Each of these parameters is | |||
optional. In the rest of this section, <tt>len</tt> denotes the length of the in put array.</t> | optional. In the rest of this section, <tt>len</tt> denotes the length of the in put array.</t> | |||
<t>The default value for <tt>step</tt> is <tt>1</tt>. | <t>The default value for <tt>step</tt> is <tt>1</tt>. | |||
The default values for <tt>start</tt> and <tt>end</tt> depend on the sign of <tt >step</tt>, | The default values for <tt>start</tt> and <tt>end</tt> depend on the sign of <tt >step</tt>, | |||
as shown in <xref target="tbl-slice-start-end"/>:</t> | as shown in <xref target="tbl-slice-start-end"/>.</t> | |||
<table anchor="tbl-slice-start-end"> | <table anchor="tbl-slice-start-end"> | |||
<name>Default array slice start and end values</name> | <name>Default Array Slice start and end Values</name> | |||
<thead> | <thead> | |||
<tr> | <tr> | |||
<th align="left">Condition</th> | <th align="left">Condition</th> | |||
<th align="left">start</th> | <th align="left">start</th> | |||
<th align="left">end</th> | <th align="left">end</th> | |||
</tr> | </tr> | |||
</thead> | </thead> | |||
<tbody> | <tbody> | |||
<tr> | <tr> | |||
<td align="left">step >= 0</td> | <td align="left">step >= 0</td> | |||
skipping to change at line 1303 ¶ | skipping to change at line 1275 ¶ | |||
ELSE if step < 0 THEN | ELSE if step < 0 THEN | |||
i = upper | i = upper | |||
WHILE lower < i: | WHILE lower < i: | |||
SELECT a(i) | SELECT a(i) | |||
i = i + step | i = i + step | |||
END WHILE | END WHILE | |||
END IF | END IF | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t>When <tt>step = 0</tt>, no elements are selected and the result array is empty.</t> | <t>When <tt>step = 0</tt>, no elements are selected, and the resul t array is empty.</t> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="examples-4"> | <section anchor="examples-4"> | |||
<name>Examples</name> | <name>Examples</name> | |||
<t>JSON:</t> | <t>JSON:</t> | |||
<sourcecode type="json"><![CDATA[ | <sourcecode type="json"><![CDATA[ | |||
["a", "b", "c", "d", "e", "f", "g"] | ["a", "b", "c", "d", "e", "f", "g"] | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t>Queries:</t> | <t>Queries:</t> | |||
<t>The examples in <xref target="tbl-slice"/> show the array slice s elector in use by a child segment:</t> | <t>The examples in <xref target="tbl-slice"/> show the array slice s elector in use by a child segment.</t> | |||
<table anchor="tbl-slice"> | <table anchor="tbl-slice"> | |||
<name>Array slice selector examples</name> | <name>Array Slice Selector Examples</name> | |||
<thead> | <thead> | |||
<tr> | <tr> | |||
<th align="center">Query</th> | <th align="center">Query</th> | |||
<th align="left">Result</th> | <th align="left">Result</th> | |||
<th align="center">Result Paths</th> | <th align="center">Result Paths</th> | |||
<th align="left">Comment</th> | <th align="left">Comment</th> | |||
</tr> | </tr> | |||
</thead> | </thead> | |||
<tbody> | <tbody> | |||
<tr> | <tr> | |||
skipping to change at line 1375 ¶ | skipping to change at line 1347 ¶ | |||
<tt>"g"</tt> <br/> <tt>"f"</tt> <br/> <tt>"e"</tt> <br/> <tt >"d"</tt> <br/> <tt>"c"</tt> <br/> <tt>"b"</tt> <br/> <tt>"a"</tt></td> | <tt>"g"</tt> <br/> <tt>"f"</tt> <br/> <tt>"e"</tt> <br/> <tt >"d"</tt> <br/> <tt>"c"</tt> <br/> <tt>"b"</tt> <br/> <tt>"a"</tt></td> | |||
<td align="center"> | <td align="center"> | |||
<tt>$[6]</tt> <br/> <tt>$[5]</tt> <br/> <tt>$[4]</tt> <br/> <tt>$[3]</tt> <br/> <tt>$[2]</tt> <br/> <tt>$[1]</tt> <br/> <tt>$[0]</tt></td> | <tt>$[6]</tt> <br/> <tt>$[5]</tt> <br/> <tt>$[4]</tt> <br/> <tt>$[3]</tt> <br/> <tt>$[2]</tt> <br/> <tt>$[1]</tt> <br/> <tt>$[0]</tt></td> | |||
<td align="left">Slice in reverse order</td> | <td align="left">Slice in reverse order</td> | |||
</tr> | </tr> | |||
</tbody> | </tbody> | |||
</table> | </table> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="filter-selector"> | <section anchor="filter-selector"> | |||
<name>Filter selector</name> | <name>Filter Selector</name> | |||
<t>Filter selectors are used to iterate over the elements or members o f | <t>Filter selectors are used to iterate over the elements or members o f | |||
structured values, i.e., JSON arrays and objects. | structured values, i.e., JSON arrays and objects. | |||
The structured values are identified in the nodelist offered by the | The structured values are identified in the nodelist offered by the | |||
child or descendant segment using the filter selector.</t> | child or descendant segment using the filter selector.</t> | |||
<t>For each iteration (element/member), a logical expression, the <em> | <t>For each iteration (element/member), a logical expression (the <em> | |||
filter expression</em>, | filter expression</em>) | |||
is evaluated which decides whether the node of | is evaluated, which decides whether the node of | |||
the element/member is selected. | the element/member is selected. | |||
(While a logical expression evaluates to what mathematically is a | (While a logical expression evaluates to what mathematically is a | |||
Boolean value, this specification uses the term <em>logical</em> to maintain a d istinction from | Boolean value, this specification uses the term <em>logical</em> to maintain a d istinction from | |||
the Boolean values that JSON can represent.)</t> | the Boolean values that JSON can represent.)</t> | |||
<t>During the iteration process, the filter expression receives the no de | <t>During the iteration process, the filter expression receives the no de | |||
of each array element or object member value of the structured value being | of each array element or object member value of the structured value being | |||
filtered; this element or member value is then known as the <em>current node</em >.</t> | filtered; this element or member value is then known as the <em>current node</em >.</t> | |||
<t>The current node can be used as the start of one or more JSONPath | <t>The current node can be used as the start of one or more JSONPath | |||
queries in subexpressions of the filter expression, notated | queries in subexpressions of the filter expression, notated | |||
via the current-node-identifier <tt>@</tt>. | via the current-node-identifier <tt>@</tt>. | |||
Each JSONPath query can be used either for testing existence of a | Each JSONPath query can be used either for testing existence of a | |||
result of the query, for obtaining a specific JSON value resulting | result of the query, for obtaining a specific JSON value resulting | |||
from that query that can then be used in a comparison, or as a | from that query that can then be used in a comparison, or as a | |||
<em>function argument</em>.</t> | <em>function argument</em>.</t> | |||
<t>Filter selectors may use function extensions, which are covered in <xref target="fnex"/>. | <t>Filter selectors may use function extensions, which are covered in <xref target="fnex"/>. | |||
Within the logical expression for a filter selector, function | Within the logical expression for a filter selector, function | |||
expressions can be used to operate on nodelists and values. | expressions can be used to operate on nodelists and values. | |||
The set of available functions is extensible, with a number of | The set of available functions is extensible, with a number of | |||
functions predefined, see <xref target="fnex"/>, and the ability to register fur | functions predefined (see <xref target="fnex"/>) and the ability to register fur | |||
ther | ther | |||
functions provided by the Function Extensions sub-registry (<xref target="iana-f | functions provided by the "Function Extensions" subregistry (<xref target="iana- | |||
nex"/>). | fnex"/>). | |||
When a function is defined, it is given a unique name, and its return value and | When a function is defined, it is given a unique name, and its return value and | |||
each of its parameters is given a | each of its parameters are given a | |||
<em>declared type</em>. | <em>declared type</em>. | |||
The type system is limited in scope; its purpose is to express | The type system is limited in scope; its purpose is to express | |||
restrictions that, without functions, are implicit in the grammar of | restrictions that, without functions, are implicit in the grammar of | |||
filter expressions. | filter expressions. | |||
The type system also guides conversions (<xref target="type-conv"/>) that mimic the | The type system also guides conversions (<xref target="type-conv"/>) that mimic the | |||
way different kinds of expressions are handled in the grammar when | way different kinds of expressions are handled in the grammar when | |||
function expressions are not in use.</t> | function expressions are not in use.</t> | |||
<section anchor="filter-selector-syntax"> | <section anchor="filter-selector-syntax"> | |||
<name>Syntax</name> | <name>Syntax</name> | |||
<t>The filter selector has the form <tt>?<logical-expr></tt>.< /t> | <t>The filter selector has the form <tt>?<logical-expr></tt>.< /t> | |||
<sourcecode type="abnf" name="jsonpath-collected.abnf"><![CDATA[ | <sourcecode type="abnf" name="jsonpath-collected.abnf"><![CDATA[ | |||
filter-selector = "?" S logical-expr | filter-selector = "?" S logical-expr | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t>As the filter expression is composed of side-effect free constitu ents, | <t>As the filter expression is composed of constituents free of side effects, | |||
the order of evaluation does not need to be (and is not) defined. | the order of evaluation does not need to be (and is not) defined. | |||
Similarly, for conjunction (<tt>&&</tt>) and disjunction (<tt>||</tt>) ( defined later), | Similarly, for conjunction (<tt>&&</tt>) and disjunction (<tt>||</tt>) ( defined later), | |||
both a short-circuiting and a fully evaluating | both a short-circuiting and a fully evaluating | |||
implementation will lead to the same result; both implementation | implementation will lead to the same result; both implementation | |||
strategies are therefore valid.</t> | strategies are therefore valid.</t> | |||
<t>The current node is accessible via the current node identifier <t t>@</tt>. | <t>The current node is accessible via the current node identifier <t t>@</tt>. | |||
This identifier addresses the current node of the filter-selector that | This identifier addresses the current node of the filter-selector that | |||
is directly enclosing the identifier. Note: within nested | is directly enclosing the identifier. Note: Within nested | |||
filter-selectors, there is no syntax to address the current node of | filter-selectors, there is no syntax to address the current node of | |||
any other than the directly enclosing filter-selector (i.e., of | any other than the directly enclosing filter-selector (i.e., of | |||
filter-selectors enclosing the filter-selector that is directly | filter-selectors enclosing the filter-selector that is directly | |||
enclosing the identifier).</t> | enclosing the identifier).</t> | |||
<t>Logical expressions offer the usual Boolean operators (<tt>||</tt > for OR, | <t>Logical expressions offer the usual Boolean operators (<tt>||</tt > for OR, | |||
<tt>&&</tt> for AND, and <tt>!</tt> for NOT). | <tt>&&</tt> for AND, and <tt>!</tt> for NOT). | |||
They have the normal semantics of Boolean algebra and obey its laws | They have the normal semantics of Boolean algebra and obey its laws | |||
(see, for example, <xref target="BOOLEAN-LAWS"/>). | (for example, see <xref target="BOOLEAN-LAWS"/>). | |||
Parentheses <bcp14>MAY</bcp14> be used within <tt>logical-expr</tt> for grouping .</t> | Parentheses <bcp14>MAY</bcp14> be used within <tt>logical-expr</tt> for grouping .</t> | |||
<t>It is not required that <tt>logical-expr</tt> consist of | <t>It is not required that <tt>logical-expr</tt> consist of | |||
a parenthesized expression (which was required in <xref target="JSONPath-orig"/> ), | a parenthesized expression (which was required in <xref target="JSONPath-orig"/> ), | |||
although it can be, and the semantics are the same | although it can be, and the semantics are the same | |||
as without the parentheses.</t> | as without the parentheses.</t> | |||
<sourcecode type="abnf" name="jsonpath-collected.abnf"><![CDATA[ | <sourcecode type="abnf" name="jsonpath-collected.abnf"><![CDATA[ | |||
logical-expr = logical-or-expr | logical-expr = logical-or-expr | |||
logical-or-expr = logical-and-expr *(S "||" S logical-and-expr) | logical-or-expr = logical-and-expr *(S "||" S logical-and-expr) | |||
; disjunction | ; disjunction | |||
; binds less tightly than conjunction | ; binds less tightly than conjunction | |||
skipping to change at line 1467 ¶ | skipping to change at line 1439 ¶ | |||
designated by an embedded query (see <xref target="extest"/>) or tests the | designated by an embedded query (see <xref target="extest"/>) or tests the | |||
result of a function expression (see <xref target="fnex"/>). | result of a function expression (see <xref target="fnex"/>). | |||
In the latter case, if the function's declared result type is | In the latter case, if the function's declared result type is | |||
<tt>LogicalType</tt> (see <xref target="typesys"/>), it tests whether the result | <tt>LogicalType</tt> (see <xref target="typesys"/>), it tests whether the result | |||
is <tt>LogicalTrue</tt>; if the function's declared result type is | is <tt>LogicalTrue</tt>; if the function's declared result type is | |||
<tt>NodesType</tt>, it tests whether the result is non-empty. | <tt>NodesType</tt>, it tests whether the result is non-empty. | |||
If the function's declared result type is <tt>ValueType</tt>, its use in a | If the function's declared result type is <tt>ValueType</tt>, its use in a | |||
test expression is not well-typed (see <xref target="well-typedness"/>).</t> | test expression is not well-typed (see <xref target="well-typedness"/>).</t> | |||
<sourcecode type="abnf" name="jsonpath-collected.abnf"><![CDATA[ | <sourcecode type="abnf" name="jsonpath-collected.abnf"><![CDATA[ | |||
test-expr = [logical-not-op S] | test-expr = [logical-not-op S] | |||
(filter-query / ; existence/non-existence | (filter-query / ; existence/non-existence | |||
function-expr) ; LogicalType or NodesType | function-expr) ; LogicalType or NodesType | |||
filter-query = rel-query / jsonpath-query | filter-query = rel-query / jsonpath-query | |||
rel-query = current-node-identifier segments | rel-query = current-node-identifier segments | |||
current-node-identifier = "@" | current-node-identifier = "@" | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t>Comparison expressions are available for comparisons between prim itive | <t>Comparison expressions are available for comparisons between prim itive | |||
values (that is, numbers, strings, <tt>true</tt>, <tt>false</tt>, and <tt>null</ tt>). | values (that is, numbers, strings, <tt>true</tt>, <tt>false</tt>, and <tt>null</ tt>). | |||
These can be obtained via literal values; singular queries, each of | These can be obtained via literal values; singular queries, each of | |||
which selects at most one node the value of which is then used; or | which selects at most one node, the value of which is then used; or | |||
function expressions (see <xref target="fnex"/>) of type <tt>ValueType</tt>.</t> | function expressions (see <xref target="fnex"/>) of type <tt>ValueType</tt>.</t> | |||
<sourcecode type="abnf" name="jsonpath-collected.abnf"><![CDATA[ | <sourcecode type="abnf" name="jsonpath-collected.abnf"><![CDATA[ | |||
comparison-expr = comparable S comparison-op S comparable | comparison-expr = comparable S comparison-op S comparable | |||
literal = number / string-literal / | literal = number / string-literal / | |||
true / false / null | true / false / null | |||
comparable = literal / | comparable = literal / | |||
singular-query / ; singular query value | singular-query / ; singular query value | |||
function-expr ; ValueType | function-expr ; ValueType | |||
comparison-op = "==" / "!=" / | comparison-op = "==" / "!=" / | |||
"<=" / ">=" / | "<=" / ">=" / | |||
skipping to change at line 1499 ¶ | skipping to change at line 1471 ¶ | |||
singular-query = rel-singular-query / abs-singular-query | singular-query = rel-singular-query / abs-singular-query | |||
rel-singular-query = current-node-identifier singular-query-segments | rel-singular-query = current-node-identifier singular-query-segments | |||
abs-singular-query = root-identifier singular-query-segments | abs-singular-query = root-identifier singular-query-segments | |||
singular-query-segments = *(S (name-segment / index-segment)) | singular-query-segments = *(S (name-segment / index-segment)) | |||
name-segment = ("[" name-selector "]") / | name-segment = ("[" name-selector "]") / | |||
("." member-name-shorthand) | ("." member-name-shorthand) | |||
index-segment = "[" index-selector "]" | index-segment = "[" index-selector "]" | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t>Literals can be notated in the way that is usual for JSON (with t he | <t>Literals can be notated in the way that is usual for JSON (with t he | |||
extension that strings can use single-quote delimiters).</t> | extension that strings can use single-quote delimiters).</t> | |||
<t>Note: Alphabetic characters in ABNF quoted strings are case-insen | <t>Note: Alphabetic characters in quoted strings are case-insensitiv | |||
sitive, so within a | e in ABNF, so within a | |||
floating point number the ABNF expression "e" can be either the character | floating point number, the ABNF expression "e" can be either the character | |||
'e' or 'E'.</t> | 'e' or 'E'.</t> | |||
<t><tt>true</tt>, <tt>false</tt>, and <tt>null</tt> are lower-case o nly (case-sensitive).</t> | <t><tt>true</tt>, <tt>false</tt>, and <tt>null</tt> are lowercase on ly (case-sensitive).</t> | |||
<sourcecode type="abnf" name="jsonpath-collected.abnf"><![CDATA[ | <sourcecode type="abnf" name="jsonpath-collected.abnf"><![CDATA[ | |||
number = (int / "-0") [ frac ] [ exp ] ; decimal number | number = (int / "-0") [ frac ] [ exp ] ; decimal number | |||
frac = "." 1*DIGIT ; decimal fraction | frac = "." 1*DIGIT ; decimal fraction | |||
exp = "e" [ "-" / "+" ] 1*DIGIT ; decimal exponent | exp = "e" [ "-" / "+" ] 1*DIGIT ; decimal exponent | |||
true = %x74.72.75.65 ; true | true = %x74.72.75.65 ; true | |||
false = %x66.61.6c.73.65 ; false | false = %x66.61.6c.73.65 ; false | |||
null = %x6e.75.6c.6c ; null | null = %x6e.75.6c.6c ; null | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t><xref target="tbl-prec"/> lists filter expression operators in or der of precedence from highest (binds most tightly) to lowest (binds least tight ly).</t> | <t><xref target="tbl-prec"/> lists filter expression operators in or der of precedence from highest (binds most tightly) to lowest (binds least tight ly).</t> | |||
<!-- FIXME: Should the syntax column be split between unary and bina | ||||
ry operators? --> | ||||
<table anchor="tbl-prec"> | <table anchor="tbl-prec"> | |||
<name>Filter expression operator precedence</name> | <name>Filter Expression Operator Precedence</name> | |||
<thead> | <thead> | |||
<tr> | <tr> | |||
<th align="center">Precedence</th> | <th align="center">Precedence</th> | |||
<th align="center">Operator type</th> | <th align="center">Operator type</th> | |||
<th align="center">Syntax</th> | <th align="center">Syntax</th> | |||
</tr> | </tr> | |||
</thead> | </thead> | |||
<tbody> | <tbody> | |||
<tr> | <tr> | |||
<td align="center">5</td> | <td align="center">5</td> | |||
skipping to change at line 1540 ¶ | skipping to change at line 1510 ¶ | |||
<tr> | <tr> | |||
<td align="center">4</td> | <td align="center">4</td> | |||
<td align="center">Logical NOT</td> | <td align="center">Logical NOT</td> | |||
<td align="center"> | <td align="center"> | |||
<tt>!</tt></td> | <tt>!</tt></td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="center">3</td> | <td align="center">3</td> | |||
<td align="center">Relations</td> | <td align="center">Relations</td> | |||
<td align="center"> | <td align="center"> | |||
<tt>==</tt> <tt>!=</tt><br/><tt><</tt> <tt><=</tt> <tt >></tt> <tt>>=</tt></td> | <tt>==</tt> <tt>!=</tt><br/><tt><</tt> <tt><=</tt> <tt >></tt> <tt>>=</tt></td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="center">2</td> | <td align="center">2</td> | |||
<td align="center">Logical AND</td> | <td align="center">Logical AND</td> | |||
<td align="center"> | <td align="center"> | |||
<tt>&&</tt></td> | <tt>&&</tt></td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="center">1</td> | <td align="center">1</td> | |||
<td align="center">Logical OR</td> | <td align="center">Logical OR</td> | |||
<td align="center"> | <td align="center"> | |||
<tt>||</tt></td> | <tt>||</tt></td> | |||
</tr> | </tr> | |||
</tbody> | </tbody> | |||
</table> | </table> | |||
</section> | </section> | |||
<section anchor="semantics-5"> | <section anchor="semantics-5"> | |||
<name>Semantics</name> | <name>Semantics</name> | |||
<t>The filter selector works with arrays and objects exclusively. It s result is a list of <em>zero</em>, <em>one</em>, <em>multiple</em> or <em>all< /em> of their array elements or member values, respectively. | <t>The filter selector works with arrays and objects exclusively. It s result is a list of (<em>zero</em>, <em>one</em>, <em>multiple</em>, or <em>al l</em>) their array elements or member values, respectively. | |||
Applied to a primitive value, it selects nothing (and therefore does | Applied to a primitive value, it selects nothing (and therefore does | |||
not contribute to the result of the filter selector).</t> | not contribute to the result of the filter selector).</t> | |||
<t>In the resultant nodelist, children of an array are ordered by th eir position in the array. | <t>In the resultant nodelist, children of an array are ordered by th eir position in the array. | |||
The order in which the children of an object (as opposed to an array) | The order in which the children of an object (as opposed to an array) | |||
appear in the resultant nodelist is not stipulated, | appear in the resultant nodelist is not stipulated, | |||
since JSON objects are unordered.</t> | since JSON objects are unordered.</t> | |||
<section anchor="extest"> | <section anchor="extest"> | |||
<name>Existence Tests</name> | <name>Existence Tests</name> | |||
<t>A query by itself in a logical context is an existence test whi ch yields true if the query selects at least one node and yields false if the qu ery does not select any nodes.</t> | <t>A query by itself in a logical context is an existence test tha t yields true if the query selects at least one node and yields false if the que ry does not select any nodes.</t> | |||
<t>Existence tests differ from comparisons in that:</t> | <t>Existence tests differ from comparisons in that:</t> | |||
<ul spacing="normal"> | <ul spacing="normal"> | |||
<li>they work with arbitrary relative or absolute queries (not j | <li>They work with arbitrary relative or absolute queries (not j | |||
ust singular queries).</li> | ust singular queries).</li> | |||
<li>they work with queries that select structured values.</li> | <li>They work with queries that select structured values.</li> | |||
</ul> | </ul> | |||
<t>To examine the value of a node selected by a query, an explicit comparison is necessary. | <t>To examine the value of a node selected by a query, an explicit comparison is necessary. | |||
For example, to test whether the node selected by the query <tt>@.foo</tt> has t he value <tt>null</tt>, use <tt>@.foo == null</tt> (see <xref target="null-seman tics"/>) | For example, to test whether the node selected by the query <tt>@.foo</tt> has t he value <tt>null</tt>, use <tt>@.foo == null</tt> (see <xref target="null-seman tics"/>) | |||
rather than the negated existence test <tt>!@.foo</tt> (which yields false if <t t>@.foo</tt> selects a node, regardless of the node's value). | rather than the negated existence test <tt>!@.foo</tt> (which yields false if <t t>@.foo</tt> selects a node, regardless of the node's value). | |||
Similarly, <tt>@.foo == false</tt> yields true only if <tt>@.foo</tt> selects a node and | Similarly, <tt>@.foo == false</tt> yields true only if <tt>@.foo</tt> selects a node and | |||
the value of that node is <tt>false</tt>.</t> | the value of that node is <tt>false</tt>.</t> | |||
</section> | </section> | |||
<section anchor="comparisons"> | <section anchor="comparisons"> | |||
<name>Comparisons</name> | <name>Comparisons</name> | |||
<t>The comparison operators <tt>==</tt> and <tt><</tt> are defi ned first and then these are used to define <tt>!=</tt>, <tt><=</tt>, <tt>> ;</tt>, and <tt>>=</tt>.</t> | <t>The comparison operators <tt>==</tt> and <tt><</tt> are defi ned first, and then these are used to define <tt>!=</tt>, <tt><=</tt>, <tt>&g t;</tt>, and <tt>>=</tt>.</t> | |||
<t>When either side of a comparison results in an empty nodelist o r the | <t>When either side of a comparison results in an empty nodelist o r the | |||
special result <tt>Nothing</tt> (see <xref target="typesys"/>):</t> | special result <tt>Nothing</tt> (see <xref target="typesys"/>):</t> | |||
<ul spacing="normal"> | <ul spacing="normal"> | |||
<li>a comparison using the operator <tt>==</tt> yields true if a nd only the | <li>A comparison using the operator <tt>==</tt> yields true if a nd only the | |||
other side also results in an empty nodelist or the special result <tt>Nothing</ tt>.</li> | other side also results in an empty nodelist or the special result <tt>Nothing</ tt>.</li> | |||
<li>a comparison using the operator <tt><</tt> yields false.< /li> | <li>A comparison using the operator <tt><</tt> yields false.< /li> | |||
</ul> | </ul> | |||
<t>When any query or function expression on either side of a compa rison results in a nodelist consisting of a single node, that side is | <t>When any query or function expression on either side of a compa rison results in a nodelist consisting of a single node, that side is | |||
replaced by the value of its node and then:</t> | replaced by the value of its node and then:</t> | |||
<ul spacing="normal"> | <ul spacing="normal"> | |||
<li> | <li> | |||
<t>a comparison using the operator <tt>==</tt> yields true if and only if the comparison | <t>A comparison using the operator <tt>==</tt> yields true if and only if the comparison | |||
is between: | is between: | |||
</t> | </t> | |||
<ul spacing="normal"> | <ul spacing="normal"> | |||
<li>numbers expected to interoperate as per <xref section="2 | <li>numbers expected to interoperate, as per <xref section=" | |||
.2" sectionFormat="of" target="RFC7493">I-JSON</xref> that compare equal using n | 2.2" sectionFormat="of" target="RFC7493">I-JSON</xref>, that compare equal using | |||
ormal mathematical equality,</li> | normal mathematical equality,</li> | |||
<li>numbers at least one of which is not expected to interop | <li>numbers, at least one of which is not expected to intero | |||
erate as per I-JSON, where the numbers compare equal using an implementation spe | perate as per I-JSON, where the numbers compare equal using an implementation-sp | |||
cific equality,</li> | ecific equality,</li> | |||
<li>equal primitive values which are not numbers,</li> | <li>equal primitive values that are not numbers,</li> | |||
<li>equal arrays, that is arrays of the same length where ea | <li>equal arrays, that is, arrays of the same length where e | |||
ch element of the first array is equal to the corresponding | ach element of the first array is equal to the corresponding | |||
element of the second array, or</li> | element of the second array, or</li> | |||
<li> | <li> | |||
<t>equal objects with no duplicate names, that is where: | <t>equal objects with no duplicate names, that is, where: | |||
</t> | </t> | |||
<ul spacing="normal"> | <ul spacing="normal"> | |||
<li>both objects have the same collection of names (with no duplicates), and</li> | <li>both objects have the same collection of names (with no duplicates) and</li> | |||
<li>for each of those names, the values associated with the name by the objects are equal.</li> | <li>for each of those names, the values associated with the name by the objects are equal.</li> | |||
</ul> | </ul> | |||
</li> | </li> | |||
</ul> | </ul> | |||
</li> | </li> | |||
<li> | <li> | |||
<t>a comparison using the operator <tt><</tt> yields true i | <t>A comparison using the operator <tt><</tt> yields true i | |||
f and only if | f and only if | |||
the comparison is between values which are both numbers or both strings and whic | the comparison is between values that are both numbers or both strings and that | |||
h satisfy the comparison: </t> | satisfy the comparison: </t> | |||
<ul spacing="normal"> | <ul spacing="normal"> | |||
<li>numbers expected to interoperate as per <xref section="2 | <li>numbers expected to interoperate, as per <xref section=" | |||
.2" sectionFormat="of" target="RFC7493">I-JSON</xref> <bcp14>MUST</bcp14> compar | 2.2" sectionFormat="of" target="RFC7493">I-JSON</xref>, <bcp14>MUST</bcp14> comp | |||
e using the normal mathematical ordering; | are using the normal mathematical ordering; | |||
numbers not expected to interoperate as per I-JSON <bcp14>MAY</bcp14> compare us | numbers not expected to interoperate, as per I-JSON, <bcp14>MAY</bcp14> compare | |||
ing an implementation specific ordering</li> | using an implementation-specific ordering,</li> | |||
<li>the empty string compares less than any non-empty string | <li>the empty string compares less than any non-empty string | |||
</li> | , and</li> | |||
<li>a non-empty string compares less than another non-empty string if and only if the first string starts with a | <li>a non-empty string compares less than another non-empty string if and only if the first string starts with a | |||
lower Unicode scalar value than the second string or if both strings start with the same Unicode scalar value and | lower Unicode scalar value than the second string or if both strings start with the same Unicode scalar value and | |||
the remainder of the first string compares less than the remainder of the second string.</li> | the remainder of the first string compares less than the remainder of the second string.</li> | |||
</ul> | </ul> | |||
</li> | </li> | |||
</ul> | </ul> | |||
<t><tt>!=</tt>, <tt><=</tt>, <tt>></tt>, and <tt>>=</tt> are defined in terms of the other comparison operators. For any <tt>a</tt> and < tt>b</tt>:</t> | <t><tt>!=</tt>, <tt><=</tt>, <tt>></tt>, and <tt>>=</tt> are defined in terms of the other comparison operators. For any <tt>a</tt> and < tt>b</tt>:</t> | |||
<ul spacing="normal"> | <ul spacing="normal"> | |||
<li>The comparison <tt>a != b</tt> yields true if and only if <t t>a == b</tt> yields false.</li> | <li>The comparison <tt>a != b</tt> yields true if and only if <t t>a == b</tt> yields false.</li> | |||
<li>The comparison <tt>a <= b</tt> yields true if and only if <tt>a < b</tt> yields true or <tt>a == b</tt> yields true.</li> | <li>The comparison <tt>a <= b</tt> yields true if and only if <tt>a < b</tt> yields true or <tt>a == b</tt> yields true.</li> | |||
skipping to change at line 1648 ¶ | skipping to change at line 1618 ¶ | |||
result with a given JSON value as input.</t> | result with a given JSON value as input.</t> | |||
<t>JSON:</t> | <t>JSON:</t> | |||
<sourcecode type="json"><![CDATA[ | <sourcecode type="json"><![CDATA[ | |||
{ | { | |||
"obj": {"x": "y"}, | "obj": {"x": "y"}, | |||
"arr": [2, 3] | "arr": [2, 3] | |||
} | } | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t>Comparisons:</t> | <t>Comparisons:</t> | |||
<table anchor="tbl-comparison"> | <table anchor="tbl-comparison"> | |||
<name>Comparison examples</name> | <name>Comparison Examples</name> | |||
<thead> | <thead> | |||
<tr> | <tr> | |||
<th align="center">Comparison</th> | <th align="center">Comparison</th> | |||
<th align="center">Result</th> | <th align="center">Result</th> | |||
<th align="center">Comment</th> | <th align="center">Comment</th> | |||
</tr> | </tr> | |||
</thead> | </thead> | |||
<tbody> | <tbody> | |||
<tr> | <tr> | |||
<td align="center"> | <td align="center"> | |||
skipping to change at line 1698 ¶ | skipping to change at line 1668 ¶ | |||
<tr> | <tr> | |||
<td align="center"> | <td align="center"> | |||
<tt>1 <= 2</tt></td> | <tt>1 <= 2</tt></td> | |||
<td align="center">true</td> | <td align="center">true</td> | |||
<td align="center">Numeric comparison</td> | <td align="center">Numeric comparison</td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="center"> | <td align="center"> | |||
<tt>1 > 2</tt></td> | <tt>1 > 2</tt></td> | |||
<td align="center">false</td> | <td align="center">false</td> | |||
<td align="center">Strict, numeric comparison</td> | <td align="center">Numeric comparison</td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="center"> | <td align="center"> | |||
<tt>13 == '13'</tt></td> | <tt>13 == '13'</tt></td> | |||
<td align="center">false</td> | <td align="center">false</td> | |||
<td align="center">Type mismatch</td> | <td align="center">Type mismatch</td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="center"> | <td align="center"> | |||
<tt>'a' <= 'b'</tt></td> | <tt>'a' <= 'b'</tt></td> | |||
<td align="center">true</td> | <td align="center">true</td> | |||
<td align="center">String comparison</td> | <td align="center">String comparison</td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="center"> | <td align="center"> | |||
<tt>'a' > 'b'</tt></td> | <tt>'a' > 'b'</tt></td> | |||
<td align="center">false</td> | <td align="center">false</td> | |||
<td align="center">Strict, string comparison</td> | <td align="center">String comparison</td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="center"> | <td align="center"> | |||
<tt>$.obj == $.arr</tt></td> | <tt>$.obj == $.arr</tt></td> | |||
<td align="center">false</td> | <td align="center">false</td> | |||
<td align="center">Type mismatch</td> | <td align="center">Type mismatch</td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="center"> | <td align="center"> | |||
<tt>$.obj != $.arr</tt></td> | <tt>$.obj != $.arr</tt></td> | |||
skipping to change at line 1832 ¶ | skipping to change at line 1802 ¶ | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="center"> | <td align="center"> | |||
<tt>true > true</tt></td> | <tt>true > true</tt></td> | |||
<td align="center">false</td> | <td align="center">false</td> | |||
<td align="center">Booleans do not offer <tt><</tt> compari son</td> | <td align="center">Booleans do not offer <tt><</tt> compari son</td> | |||
</tr> | </tr> | |||
</tbody> | </tbody> | |||
</table> | </table> | |||
<t>The second set of examples shows some complete JSONPath queries t hat make use | <t>The second set of examples shows some complete JSONPath queries t hat make use | |||
of filter selectors, and the results of evaluating these queries on a | of filter selectors and the results of evaluating these queries on a | |||
given JSON value as input. | given JSON value as input. | |||
(Note: two of the queries employ function extensions; please see | (Note: Two of the queries employ function extensions; please see | |||
Sections <xref format="counter" target="match"/> and <xref format="counter" targ | Sections <xref format="counter" target="match"/> and <xref format="counter" targ | |||
et="search"/> below for details about these.)</t> | et="search"/> for details about these.)</t> | |||
<t>JSON:</t> | <t>JSON:</t> | |||
<sourcecode type="json"><![CDATA[ | <sourcecode type="json"><![CDATA[ | |||
{ | { | |||
"a": [3, 5, 1, 2, 4, 6, | "a": [3, 5, 1, 2, 4, 6, | |||
{"b": "j"}, | {"b": "j"}, | |||
{"b": "k"}, | {"b": "k"}, | |||
{"b": {}}, | {"b": {}}, | |||
{"b": "kilo"} | {"b": "kilo"} | |||
], | ], | |||
"o": {"p": 1, "q": 2, "r": 3, "s": 5, "t": {"u": 6}}, | "o": {"p": 1, "q": 2, "r": 3, "s": 5, "t": {"u": 6}}, | |||
"e": "f" | "e": "f" | |||
} | } | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t>Queries:</t> | <t>Queries:</t> | |||
<t>The examples in <xref target="tbl-filter"/> show the filter selec tor in use by a child segment:</t> | <t>The examples in <xref target="tbl-filter"/> show the filter selec tor in use by a child segment.</t> | |||
<table anchor="tbl-filter"> | <table anchor="tbl-filter"> | |||
<name>Filter selector examples</name> | <name>Filter Selector Examples</name> | |||
<thead> | <thead> | |||
<tr> | <tr> | |||
<th align="center">Query</th> | <th align="center">Query</th> | |||
<th align="left">Result</th> | <th align="left">Result</th> | |||
<th align="center">Result Paths</th> | <th align="center">Result Paths</th> | |||
<th align="left">Comment</th> | <th align="left">Comment</th> | |||
</tr> | </tr> | |||
</thead> | </thead> | |||
<tbody> | <tbody> | |||
<tr> | <tr> | |||
skipping to change at line 2009 ¶ | skipping to change at line 1979 ¶ | |||
<t>The example above with the query <tt>$.o[?@<3, ?@<3]</tt> s hows that a filter selector may produce nodelists in distinct | <t>The example above with the query <tt>$.o[?@<3, ?@<3]</tt> s hows that a filter selector may produce nodelists in distinct | |||
orders each time it appears in the child segment.</t> | orders each time it appears in the child segment.</t> | |||
</section> | </section> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="fnex"> | <section anchor="fnex"> | |||
<name>Function Extensions</name> | <name>Function Extensions</name> | |||
<t>Beyond the filter expression functionality defined in the preceding | <t>Beyond the filter expression functionality defined in the preceding | |||
subsections, JSONPath defines an extension point that can be used to | subsections, JSONPath defines an extension point that can be used to | |||
add filter expression functionality: "Function Extensions".</t> | add filter expression functionality: "Function Extensions".</t> | |||
<t>This section defines the extension point as well as some function | <t>This section defines the extension point and some function | |||
extensions that use this extension point. | extensions that use this extension point. | |||
While these mechanisms are designed to use the extension point, | While these mechanisms are designed to use the extension point, | |||
they are an integral part of the JSONPath specification and are | they are an integral part of the JSONPath specification and are | |||
expected to be implemented like any other integral part of this | expected to be implemented like any other integral part of this | |||
specification.</t> | specification.</t> | |||
<t>A function extension defines a registered name (see <xref target="ian a-fnex"/>) that | <t>A function extension defines a registered name (see <xref target="ian a-fnex"/>) that | |||
can be applied to a sequence of zero or more arguments, producing a | can be applied to a sequence of zero or more arguments, producing a | |||
result. Each registered function name is unique.</t> | result. Each registered function name is unique.</t> | |||
<t>A function extension <bcp14>MUST</bcp14> be defined such that its eva luation is | <t>A function extension <bcp14>MUST</bcp14> be defined such that its eva luation is | |||
side-effect free, i.e., all possible orders of evaluation and choices | free of side effects, i.e., all possible orders of evaluation and choices | |||
of short-circuiting or full evaluation of an expression containing it | of short-circuiting or full evaluation of an expression containing it | |||
<bcp14>MUST</bcp14> lead to the same result. | <bcp14>MUST</bcp14> lead to the same result. | |||
(Note: memoization or logging are not side effects in this sense | (Note: Memoization or logging are not side effects in this sense | |||
as they are visible at the implementation level only — they do not | as they are visible at the implementation level only -- they do not | |||
influence the result of the evaluation.)</t> | influence the result of the evaluation.)</t> | |||
<sourcecode type="abnf" name="jsonpath-collected.abnf"><![CDATA[ | <sourcecode type="abnf" name="jsonpath-collected.abnf"><![CDATA[ | |||
function-name = function-name-first *function-name-char | function-name = function-name-first *function-name-char | |||
function-name-first = LCALPHA | function-name-first = LCALPHA | |||
function-name-char = function-name-first / "_" / DIGIT | function-name-char = function-name-first / "_" / DIGIT | |||
LCALPHA = %x61-7A ; "a".."z" | LCALPHA = %x61-7A ; "a".."z" | |||
function-expr = function-name "(" S [function-argument | function-expr = function-name "(" S [function-argument | |||
*(S "," S function-argument)] S ")" | *(S "," S function-argument)] S ")" | |||
function-argument = literal / | function-argument = literal / | |||
filter-query / ; (includes singular-query) | filter-query / ; (includes singular-query) | |||
logical-expr / | logical-expr / | |||
function-expr | function-expr | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t>Any function expressions in a query must be well-formed (by conformin g to the above ABNF) | <t>Any function expressions in a query must be well-formed (by conformin g to the above ABNF) | |||
and well-typed, | and well-typed; | |||
otherwise the JSONPath implementation <bcp14>MUST</bcp14> raise an error | otherwise, the JSONPath implementation <bcp14>MUST</bcp14> raise an error | |||
(see <xref target="synsem-overview"/>). | (see <xref target="synsem-overview"/>). | |||
To define which function expressions are well-typed, | To define which function expressions are well-typed, | |||
a type system is first introduced.</t> | a type system is first introduced.</t> | |||
<section anchor="typesys"> | <section anchor="typesys"> | |||
<name>Type System for Function Expressions</name> | <name>Type System for Function Expressions</name> | |||
<t>Each parameter as well as the result of a function extension must h ave a declared type.</t> | <t>Each parameter and the result of a function extension must have a d eclared type.</t> | |||
<t>Declared types enable checking a JSONPath query for well-typedness | <t>Declared types enable checking a JSONPath query for well-typedness | |||
independent of any query argument the JSONPath query is applied to.</t> | independent of any query argument the JSONPath query is applied to.</t> | |||
<t><xref target="tbl-types"/> defines the available types in terms of the instances they contain.</t> | <t><xref target="tbl-types"/> defines the available types in terms of the instances they contain.</t> | |||
<table anchor="tbl-types"> | <table anchor="tbl-types"> | |||
<name>Function extension type system</name> | <name>Function Extension Type System</name> | |||
<thead> | <thead> | |||
<tr> | <tr> | |||
<th align="left">Type</th> | <th align="left">Type</th> | |||
<th align="left">Instances</th> | <th align="left">Instances</th> | |||
</tr> | </tr> | |||
</thead> | </thead> | |||
<tbody> | <tbody> | |||
<tr> | <tr> | |||
<td align="left"> | <td align="left"> | |||
<tt>ValueType</tt></td> | <tt>ValueType</tt></td> | |||
skipping to change at line 2114 ¶ | skipping to change at line 2084 ¶ | |||
<tt>ValueType</tt> by wrapping the expression in a call to a function extension, | <tt>ValueType</tt> by wrapping the expression in a call to a function extension, | |||
such as <tt>value()</tt> (see <xref target="value"/>), | such as <tt>value()</tt> (see <xref target="value"/>), | |||
that takes a parameter of type <tt>NodesType</tt> and returns a | that takes a parameter of type <tt>NodesType</tt> and returns a | |||
result of type <tt>ValueType</tt>.</li> | result of type <tt>ValueType</tt>.</li> | |||
</ul> | </ul> | |||
<t>The well-typedness of function expressions can now be defined in te rms of this type system.</t> | <t>The well-typedness of function expressions can now be defined in te rms of this type system.</t> | |||
</section> | </section> | |||
<section anchor="well-typedness"> | <section anchor="well-typedness"> | |||
<name>Well-Typedness of Function Expressions</name> | <name>Well-Typedness of Function Expressions</name> | |||
<t>For a function expression to be well-typed:</t> | <t>For a function expression to be well-typed:</t> | |||
<ol spacing="normal" type="1"><li>its declared type must be well-typed | <ol spacing="normal" type="1"> | |||
in the context in which it occurs, and</li> | <li><t>Its declared type must be well-typed in the context in which i | |||
<li>its arguments must be well-typed for the declared type of the co | t occurs.</t> | |||
rresponding parameters.</li> | <t>As per the grammar, a function expression can occur in three different | |||
</ol> | ||||
<t>(1) As per the grammar, a function expression can occur in three di | ||||
fferent | ||||
immediate contexts, which lead to the following conditions for well-typedness:</ t> | immediate contexts, which lead to the following conditions for well-typedness:</ t> | |||
<dl newline="true"> | <dl newline="true"> | |||
<dt>As a <tt>test-expr</tt> in a logical expression:</dt> | <dt>As a <tt>test-expr</tt> in a logical expression:</dt> | |||
<dd> | <dd> | |||
<t>The function's declared result type is <tt>LogicalType</tt>, or | <t>The function's declared result type is <tt>LogicalType</tt> or | |||
(giving rise to conversion as per <xref target="type-conv"/>) <tt>NodesType</tt> .</t> | (giving rise to conversion as per <xref target="type-conv"/>) <tt>NodesType</tt> .</t> | |||
</dd> | </dd> | |||
<dt>As a <tt>comparable</tt> in a comparison:</dt> | <dt>As a <tt>comparable</tt> in a comparison:</dt> | |||
<dd> | <dd> | |||
<t>The function's declared result type is <tt>ValueType</tt>.</t> | <t>The function's declared result type is <tt>ValueType</tt>.</t> | |||
</dd> | </dd> | |||
<dt>As a <tt>function-argument</tt> in another function expression:< /dt> | <dt>As a <tt>function-argument</tt> in another function expression:< /dt> | |||
<dd> | <dd> | |||
<t>The function's declared result type fulfills the following rule s for | <t>The function's declared result type fulfills the following rule s for | |||
the corresponding parameter of the enclosing function.</t> | the corresponding parameter of the enclosing function.</t> | |||
</dd> | </dd> | |||
</dl> | </dl> | |||
<t>(2) The arguments of the function expression are well-typed when | </li> | |||
<li><t>Its arguments must be well-typed for the declared type of the | ||||
corresponding parameters.</t> | ||||
<t>The arguments of the function expression are well-typed when | ||||
each argument of the function can be used for the declared type of the | each argument of the function can be used for the declared type of the | |||
corresponding parameter, according to one of the following | corresponding parameter, according to one of the following | |||
conditions:</t> | conditions:</t> | |||
<ul spacing="normal"> | <ul spacing="normal"> | |||
<li>When the argument is a function expression with declared result type the same as the | <li>When the argument is a function expression with the same declare d result type as the | |||
declared type of the parameter.</li> | declared type of the parameter.</li> | |||
<li> | <li> | |||
<t>When the declared type of the parameter is <tt>LogicalType</tt> and the argument is one of the following: | <t>When the declared type of the parameter is <tt>LogicalType</tt> and the argument is one of the following: | |||
</t> | </t> | |||
<ul spacing="normal"> | <ul spacing="normal"> | |||
<li>A function expression with declared result type <tt>NodesTyp e</tt>. | <li>A function expression with declared result type <tt>NodesTyp e</tt>. | |||
In this case the argument is converted to LogicalType as per <xref target="type- conv"/>.</li> | In this case, the argument is converted to LogicalType as per <xref target="type -conv"/>.</li> | |||
<li>A <tt>logical-expr</tt> that is not a function expression.</ li> | <li>A <tt>logical-expr</tt> that is not a function expression.</ li> | |||
</ul> | </ul> | |||
</li> | </li> | |||
<li>When the declared type of the parameter is <tt>NodesType</tt> an d the argument is a query | <li>When the declared type of the parameter is <tt>NodesType</tt> an d the argument is a query | |||
(which includes singular query).</li> | (which includes singular query).</li> | |||
<li> | <li> | |||
<t>When the declared type of the parameter is <tt>ValueType</tt> a nd the argument is one of the following: | <t>When the declared type of the parameter is <tt>ValueType</tt> a nd the argument is one of the following: | |||
</t> | </t> | |||
<ul spacing="normal"> | <ul spacing="normal"> | |||
<li>A value expressed as a literal.</li> | <li>A value expressed as a literal.</li> | |||
skipping to change at line 2169 ¶ | skipping to change at line 2140 ¶ | |||
<t>A singular query. In this case: | <t>A singular query. In this case: | |||
</t> | </t> | |||
<ul spacing="normal"> | <ul spacing="normal"> | |||
<li>If the query results in a nodelist consisting of a singl e node, the | <li>If the query results in a nodelist consisting of a singl e node, the | |||
argument is the value of the node.</li> | argument is the value of the node.</li> | |||
<li>If the query results in an empty nodelist, the argument is | <li>If the query results in an empty nodelist, the argument is | |||
the special result <tt>Nothing</tt>.</li> | the special result <tt>Nothing</tt>.</li> | |||
</ul> | </ul> | |||
</li> | </li> | |||
</ul> | </ul> | |||
</li> | </li> | |||
</ul> | </ul> | |||
</li> | ||||
</ol> | ||||
</section> | </section> | |||
<section anchor="length"> | <section anchor="length"> | |||
<name><tt>length()</tt> Function Extension</name> | <name><tt>length()</tt> Function Extension</name> | |||
<dl> | <dl> | |||
<dt>Parameters:</dt> | <dt>Parameters:</dt> | |||
<dd> | <dd> | |||
<ol spacing="normal" type="1"><li> | <ol spacing="normal" type="1"><li> | |||
<tt>ValueType</tt></li> | <tt>ValueType</tt></li> | |||
</ol> | </ol> | |||
</dd> | </dd> | |||
<dt>Result:</dt> | <dt>Result:</dt> | |||
<dd> | <dd> | |||
<t><tt>ValueType</tt> (unsigned integer or <tt>Nothing</tt>)</t> | <t><tt>ValueType</tt> (unsigned integer or <tt>Nothing</tt>)</t> | |||
</dd> | </dd> | |||
</dl> | </dl> | |||
<t>The <tt>length()</tt> function extension provides a way to compute the length | <t>The <tt>length()</tt> function extension provides a way to compute the length | |||
of a value and make that available for further processing in the | of a value and make that available for further processing in the | |||
filter expression:</t> | filter expression:</t> | |||
<sourcecode type="JSONPath"><![CDATA[ | <sourcecode type="application/jsonpath"><![CDATA[ | |||
$[?length(@.authors) >= 5] | $[?length(@.authors) >= 5] | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t>Its only argument is an instance of <tt>ValueType</tt> (possibly ta ken from a | <t>Its only argument is an instance of <tt>ValueType</tt> (possibly ta ken from a | |||
singular query, as in the example above). The result also is an | singular query, as in the example above). The result is also an | |||
instance of <tt>ValueType</tt>: an unsigned integer or the special result <tt>No thing</tt>.</t> | instance of <tt>ValueType</tt>: an unsigned integer or the special result <tt>No thing</tt>.</t> | |||
<ul spacing="normal"> | <ul spacing="normal"> | |||
<li>If the argument value is a string, the result is the number of | <li>If the argument value is a string, the result is the number of | |||
Unicode scalar values in the string.</li> | Unicode scalar values in the string.</li> | |||
<li>If the argument value is an array, the result is the number of | <li>If the argument value is an array, the result is the number of | |||
elements in the array.</li> | elements in the array.</li> | |||
<li>If the argument value is an object, the result is the number of | <li>If the argument value is an object, the result is the number of | |||
members in the object.</li> | members in the object.</li> | |||
<li>For any other argument value, the result is the special result < tt>Nothing</tt>.</li> | <li>For any other argument value, the result is the special result < tt>Nothing</tt>.</li> | |||
</ul> | </ul> | |||
skipping to change at line 2222 ¶ | skipping to change at line 2195 ¶ | |||
</ol> | </ol> | |||
</dd> | </dd> | |||
<dt>Result:</dt> | <dt>Result:</dt> | |||
<dd> | <dd> | |||
<t><tt>ValueType</tt> (unsigned integer)</t> | <t><tt>ValueType</tt> (unsigned integer)</t> | |||
</dd> | </dd> | |||
</dl> | </dl> | |||
<t>The <tt>count()</tt> function extension provides a way to obtain th e number of | <t>The <tt>count()</tt> function extension provides a way to obtain th e number of | |||
nodes in a nodelist and make that available for further processing in | nodes in a nodelist and make that available for further processing in | |||
the filter expression:</t> | the filter expression:</t> | |||
<sourcecode type="JSONPath"><![CDATA[ | <sourcecode type="application/jsonpath"><![CDATA[ | |||
$[?count(@.*.author) >= 5] | $[?count(@.*.author) >= 5] | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t>Its only argument is a nodelist. | <t>Its only argument is a nodelist. | |||
The result is a value, an unsigned integer, that gives the number of | The result is a value (an unsigned integer) that gives the number of | |||
nodes in the nodelist. | nodes in the nodelist.</t> | |||
Notes:</t> | <t>Notes:</t> | |||
<ul spacing="normal"> | <ul spacing="normal"> | |||
<li>There is no deduplication of the nodelist.</li> | <li>There is no deduplication of the nodelist.</li> | |||
<li>The number of nodes in the nodelist is counted independent of th eir | <li>The number of nodes in the nodelist is counted independent of th eir | |||
values or any children they may have; e.g., the count of a non-empty | values or any children they may have, e.g., the count of a non-empty | |||
singular nodelist such as <tt>count(@)</tt> is always 1.</li> | singular nodelist such as <tt>count(@)</tt> is always 1.</li> | |||
</ul> | </ul> | |||
</section> | </section> | |||
<section anchor="match"> | <section anchor="match"> | |||
<name><tt>match()</tt> Function Extension</name> | <name><tt>match()</tt> Function Extension</name> | |||
<dl> | <dl> | |||
<dt>Parameters:</dt> | <dt>Parameters:</dt> | |||
<dd> | <dd> | |||
<ol spacing="normal" type="1"><li> | <ol spacing="normal" type="1"><li> | |||
<tt>ValueType</tt> (string)</li> | <tt>ValueType</tt> (string)</li> | |||
<li> | <li> | |||
<tt>ValueType</tt> (string conforming to <xref target="I-D.dra ft-ietf-jsonpath-iregexp"/>)</li> | <tt>ValueType</tt> (string conforming to <xref target="RFC9485 "/>)</li> | |||
</ol> | </ol> | |||
</dd> | </dd> | |||
<dt>Result:</dt> | <dt>Result:</dt> | |||
<dd> | <dd> | |||
<t><tt>LogicalType</tt></t> | <t><tt>LogicalType</tt></t> | |||
</dd> | </dd> | |||
</dl> | </dl> | |||
<t>The <tt>match()</tt> function extension provides a way to check whe ther (the | <t>The <tt>match()</tt> function extension provides a way to check whe ther (the | |||
entirety of, see <xref target="search"/> below) a given | entirety of; see <xref target="search"/>) a given | |||
string matches a given regular expression, which is in <xref target="I-D.draft-i | string matches a given regular expression, which is in the form described in <xr | |||
etf-jsonpath-iregexp"/> form.</t> | ef target="RFC9485"/>.</t> | |||
<sourcecode type="JSONPath"><![CDATA[ | <sourcecode type="application/jsonpath"><![CDATA[ | |||
$[?match(@.date, "1974-05-..")] | $[?match(@.date, "1974-05-..")] | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t>Its arguments are instances of <tt>ValueType</tt> (possibly taken f rom a | <t>Its arguments are instances of <tt>ValueType</tt> (possibly taken f rom a | |||
singular query, as for the first argument in the example above). | singular query, as for the first argument in the example above). | |||
If the first argument is not a string or the second argument is not a | If the first argument is not a string or the second argument is not a | |||
string conforming to <xref target="I-D.draft-ietf-jsonpath-iregexp"/>, the resul t is <tt>LogicalFalse</tt>. | string conforming to <xref target="RFC9485"/>, the result is <tt>LogicalFalse</t t>. | |||
Otherwise, the string that is the first argument is matched against | Otherwise, the string that is the first argument is matched against | |||
the iregexp contained in the string that is the second argument; | the I-Regexp contained in the string that is the second argument; | |||
the result is <tt>LogicalTrue</tt> if the string matches the iregexp and | the result is <tt>LogicalTrue</tt> if the string matches the I-Regexp and is | |||
<tt>LogicalFalse</tt> otherwise.</t> | <tt>LogicalFalse</tt> otherwise.</t> | |||
</section> | </section> | |||
<section anchor="search"> | <section anchor="search"> | |||
<name><tt>search()</tt> Function Extension</name> | <name><tt>search()</tt> Function Extension</name> | |||
<dl> | <dl> | |||
<dt>Parameters:</dt> | <dt>Parameters:</dt> | |||
<dd> | <dd> | |||
<ol spacing="normal" type="1"><li> | <ol spacing="normal" type="1"><li> | |||
<tt>ValueType</tt> (string)</li> | <tt>ValueType</tt> (string)</li> | |||
<li> | <li> | |||
<tt>ValueType</tt> (string conforming to <xref target="I-D.dra ft-ietf-jsonpath-iregexp"/>)</li> | <tt>ValueType</tt> (string conforming to <xref target="RFC9485 "/>)</li> | |||
</ol> | </ol> | |||
</dd> | </dd> | |||
<dt>Result:</dt> | <dt>Result:</dt> | |||
<dd> | <dd> | |||
<t><tt>LogicalType</tt></t> | <t><tt>LogicalType</tt></t> | |||
</dd> | </dd> | |||
</dl> | </dl> | |||
<t>The <tt>search()</tt> function extension provides a way to check wh ether a | <t>The <tt>search()</tt> function extension provides a way to check wh ether a | |||
given string contains a substring that matches a given regular | given string contains a substring that matches a given regular | |||
expression, which is in <xref target="I-D.draft-ietf-jsonpath-iregexp"/> form.</ | expression, which is in the form described in <xref target="RFC9485"/>.</t> | |||
t> | <sourcecode type="application/jsonpath"><![CDATA[ | |||
<sourcecode type="JSONPath"><![CDATA[ | ||||
$[?search(@.author, "[BR]ob")] | $[?search(@.author, "[BR]ob")] | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t>Its arguments are instances of <tt>ValueType</tt> (possibly taken f rom a | <t>Its arguments are instances of <tt>ValueType</tt> (possibly taken f rom a | |||
singular query, as for the first argument in the example above). | singular query, as for the first argument in the example above). | |||
If the first argument is not a string or the second argument is not a | If the first argument is not a string or the second argument is not a | |||
string conforming to <xref target="I-D.draft-ietf-jsonpath-iregexp"/>, the resul | string conforming to <xref target="RFC9485"/>, the result is <tt>LogicalFalse</t | |||
t is <tt>LogicalFalse</tt>. | t>. | |||
Otherwise, the string that is the first argument is searched for at | Otherwise, the string that is the first argument is searched for a | |||
least one substring that matches the iregexp contained in the string | substring that matches the I-Regexp contained in the string | |||
that is the second argument; the result is <tt>LogicalTrue</tt> if such a | that is the second argument; the result is <tt>LogicalTrue</tt> if at | |||
substring exists and <tt>LogicalFalse</tt> otherwise.</t> | least one such substring exists and is <tt>LogicalFalse</tt> otherwise.</t> | |||
</section> | </section> | |||
<section anchor="value"> | <section anchor="value"> | |||
<name><tt>value()</tt> Function Extension</name> | <name><tt>value()</tt> Function Extension</name> | |||
<dl> | <dl> | |||
<dt>Parameters:</dt> | <dt>Parameters:</dt> | |||
<dd> | <dd> | |||
<ol spacing="normal" type="1"><li> | <ol spacing="normal" type="1"><li> | |||
<tt>NodesType</tt></li> | <tt>NodesType</tt></li> | |||
</ol> | </ol> | |||
</dd> | </dd> | |||
<dt>Result:</dt> | <dt>Result:</dt> | |||
<dd> | <dd> | |||
<t><tt>ValueType</tt></t> | <t><tt>ValueType</tt></t> | |||
</dd> | </dd> | |||
</dl> | </dl> | |||
<t>The <tt>value()</tt> function extension provides a way to convert a n instance of <tt>NodesType</tt> to a value and | <t>The <tt>value()</tt> function extension provides a way to convert a n instance of <tt>NodesType</tt> to a value and | |||
make that available for further processing in the filter expression:</t> | make that available for further processing in the filter expression:</t> | |||
<sourcecode type="JSONPath"><![CDATA[ | <sourcecode type="application/jsonpath"><![CDATA[ | |||
$[?value(@..color) == "red"] | $[?value(@..color) == "red"] | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t>Its only argument is an instance of <tt>NodesType</tt> (possibly ta ken from a | <t>Its only argument is an instance of <tt>NodesType</tt> (possibly ta ken from a | |||
<tt>filter-query</tt>, as in the example above). The result is an | <tt>filter-query</tt>, as in the example above). The result is an | |||
instance of <tt>ValueType</tt>.</t> | instance of <tt>ValueType</tt>.</t> | |||
<ul spacing="normal"> | <ul spacing="normal"> | |||
<li>If the argument contains a single node, the result is | <li>If the argument contains a single node, the result is | |||
the value of the node.</li> | the value of the node.</li> | |||
<li>If the argument is the special result <tt>Nothing</tt> or contai ns multiple nodes, the | <li>If the argument is the empty nodelist or contains multiple nodes , the | |||
result is <tt>Nothing</tt>.</li> | result is <tt>Nothing</tt>.</li> | |||
</ul> | </ul> | |||
<t>Note: a singular query may be used anywhere where a ValueType is ex pected, | <t>Note: A singular query may be used anywhere where a ValueType is ex pected, | |||
so there is no need to use the <tt>value()</tt> function extension with a singul ar query.</t> | so there is no need to use the <tt>value()</tt> function extension with a singul ar query.</t> | |||
</section> | </section> | |||
<section anchor="examples-6"> | <section anchor="examples-6"> | |||
<name>Examples</name> | <name>Examples</name> | |||
<table anchor="tbl-function-expr"> | <table anchor="tbl-function-expr"> | |||
<name>Function expression examples</name> | <name>Function Expression Examples</name> | |||
<thead> | <thead> | |||
<tr> | <tr> | |||
<th align="center">Query</th> | <th align="center">Query</th> | |||
<th align="left">Comment</th> | <th align="left">Comment</th> | |||
</tr> | </tr> | |||
</thead> | </thead> | |||
<tbody> | <tbody> | |||
<tr> | <tr> | |||
<td align="center"> | <td align="center"> | |||
<tt>$[?length(@) < 3]</tt></td> | <tt>$[?length(@) < 3]</tt></td> | |||
skipping to change at line 2429 ¶ | skipping to change at line 2402 ¶ | |||
concatenated in the order of the input nodelist to form a single | concatenated in the order of the input nodelist to form a single | |||
segment result nodelist.</t> | segment result nodelist.</t> | |||
<t>It turns out that the more segments there are in a query, the greater the depth in the input value of the | <t>It turns out that the more segments there are in a query, the greater the depth in the input value of the | |||
nodes of the resultant nodelist:</t> | nodes of the resultant nodelist:</t> | |||
<ul spacing="normal"> | <ul spacing="normal"> | |||
<li>A query with N segments, where N >= 0, produces a nodelist | <li>A query with N segments, where N >= 0, produces a nodelist | |||
consisting of nodes at depth in the input value of N or greater.</li> | consisting of nodes at depth in the input value of N or greater.</li> | |||
<li>A query with N segments, where N >= 0, all of which are <xref t arget="child-segment">child segments</xref>, | <li>A query with N segments, where N >= 0, all of which are <xref t arget="child-segment">child segments</xref>, | |||
produces a nodelist consisting of nodes precisely at depth N in the input value. </li> | produces a nodelist consisting of nodes precisely at depth N in the input value. </li> | |||
</ul> | </ul> | |||
<t>There are two kinds of segment: child segments and descendant segment s.</t> | <t>There are two kinds of segments: child segments and descendant segmen ts.</t> | |||
<sourcecode type="abnf" name="jsonpath-collected.abnf"><![CDATA[ | <sourcecode type="abnf" name="jsonpath-collected.abnf"><![CDATA[ | |||
segment = child-segment / descendant-segment | segment = child-segment / descendant-segment | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t>The syntax and semantics of each kind of segment are defined below.</ t> | <t>The syntax and semantics of each kind of segment are defined below.</ t> | |||
<section anchor="child-segment"> | <section anchor="child-segment"> | |||
<name>Child Segment</name> | <name>Child Segment</name> | |||
<section anchor="syntax-4"> | <section anchor="syntax-4"> | |||
<name>Syntax</name> | <name>Syntax</name> | |||
<t>The child segment consists of a non-empty, comma-separated | <t>The child segment consists of a non-empty, comma-separated | |||
sequence of selectors enclosed in square brackets.</t> | sequence of selectors enclosed in square brackets.</t> | |||
skipping to change at line 2453 ¶ | skipping to change at line 2426 ¶ | |||
child-segment = bracketed-selection / | child-segment = bracketed-selection / | |||
("." | ("." | |||
(wildcard-selector / | (wildcard-selector / | |||
member-name-shorthand)) | member-name-shorthand)) | |||
bracketed-selection = "[" S selector *(S "," S selector) S "]" | bracketed-selection = "[" S selector *(S "," S selector) S "]" | |||
member-name-shorthand = name-first *name-char | member-name-shorthand = name-first *name-char | |||
name-first = ALPHA / | name-first = ALPHA / | |||
"_" / | "_" / | |||
%x80-D7FF / ; skip surrogate code points | %x80-D7FF / | |||
; skip surrogate code points | ||||
%xE000-10FFFF | %xE000-10FFFF | |||
name-char = DIGIT / name-first | name-char = name-first / DIGIT | |||
DIGIT = %x30-39 ; 0-9 | DIGIT = %x30-39 ; 0-9 | |||
ALPHA = %x41-5A / %x61-7A ; A-Z / a-z | ALPHA = %x41-5A / %x61-7A ; A-Z / a-z | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t><tt>.*</tt>, a <tt>child-segment</tt> directly built from a <tt>w ildcard-selector</tt>, is | <t><tt>.*</tt>, a <tt>child-segment</tt> directly built from a <tt>w ildcard-selector</tt>, is | |||
shorthand for <tt>[*]</tt>.</t> | shorthand for <tt>[*]</tt>.</t> | |||
<t><tt>.<member-name></tt>, a <tt>child-segment</tt> built fro m a | <t><tt>.<member-name></tt>, a <tt>child-segment</tt> built fro m a | |||
<tt>member-name-shorthand</tt>, is shorthand for <tt>['<member-name>']</t t>. | <tt>member-name-shorthand</tt>, is shorthand for <tt>['<member-name>']</t t>. | |||
Note: this can only be used with member names that are composed of certain | Note: This can only be used with member names that are composed of certain | |||
characters, as specified in the ABNF rule <tt>member-name-shorthand</tt>. | characters, as specified in the ABNF rule <tt>member-name-shorthand</tt>. | |||
Thus, for example, <tt>$.foo.bar</tt> is shorthand for <tt>$['foo']['bar']</tt> (but not for <tt>$['foo.bar']</tt>).</t> | Thus, for example, <tt>$.foo.bar</tt> is shorthand for <tt>$['foo']['bar']</tt> (but not for <tt>$['foo.bar']</tt>).</t> | |||
</section> | </section> | |||
<section anchor="semantics-6"> | <section anchor="semantics-6"> | |||
<name>Semantics</name> | <name>Semantics</name> | |||
<t>A child segment contains a sequence of selectors, each of which | <t>A child segment contains a sequence of selectors, each of which | |||
selects zero or more children of the input value.</t> | selects zero or more children of the input value.</t> | |||
<t>Selectors of different kinds may be combined within a single chil d segment.</t> | <t>Selectors of different kinds may be combined within a single chil d segment.</t> | |||
<t>For each node in the input nodelist, | <t>For each node in the input nodelist, | |||
the resulting nodelist of a child segment is the concatenation of | the resulting nodelist of a child segment is the concatenation of | |||
the nodelists from each of its selectors in the order that the selectors | the nodelists from each of its selectors in the order that the selectors | |||
appear in the list. | appear in the list. | |||
Note: any node matched by more than one selector is kept | Note: Any node matched by more than one selector is kept | |||
as many times in the nodelist.</t> | as many times in the nodelist.</t> | |||
<t>Where a selector can produce a nodelist in more than one possible order, | <t>Where a selector can produce a nodelist in more than one possible order, | |||
each occurrence of the selector in the child segment | each occurrence of the selector in the child segment | |||
may evaluate to produce a nodelist in a distinct order.</t> | may produce a nodelist in a distinct order.</t> | |||
<t>So a child segment drills down one more level into the structure | <t>In summary, a child segment drills down one more level into the st | |||
of the input value.</t> | ructure of the input value.</t> | |||
</section> | </section> | |||
<section anchor="examples-7"> | <section anchor="examples-7"> | |||
<name>Examples</name> | <name>Examples</name> | |||
<t>JSON:</t> | <t>JSON:</t> | |||
<sourcecode type="json"><![CDATA[ | <sourcecode type="json"><![CDATA[ | |||
["a", "b", "c", "d", "e", "f", "g"] | ["a", "b", "c", "d", "e", "f", "g"] | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t>Queries:</t> | <t>Queries:</t> | |||
<table anchor="tbl-child-segment"> | <table anchor="tbl-child-segment"> | |||
<name>Child segment examples</name> | <name>Child Segment Examples</name> | |||
<thead> | <thead> | |||
<tr> | <tr> | |||
<th align="center">Query</th> | <th align="center">Query</th> | |||
<th align="left">Result</th> | <th align="left">Result</th> | |||
<th align="center">Result Paths</th> | <th align="center">Result Paths</th> | |||
<th align="left">Comment</th> | <th align="left">Comment</th> | |||
</tr> | </tr> | |||
</thead> | </thead> | |||
<tbody> | <tbody> | |||
<tr> | <tr> | |||
skipping to change at line 2539 ¶ | skipping to change at line 2513 ¶ | |||
</tbody> | </tbody> | |||
</table> | </table> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="descendant-segment"> | <section anchor="descendant-segment"> | |||
<name>Descendant Segment</name> | <name>Descendant Segment</name> | |||
<section anchor="syntax-5"> | <section anchor="syntax-5"> | |||
<name>Syntax</name> | <name>Syntax</name> | |||
<t>The descendant segment consists of a double dot <tt>..</tt> | <t>The descendant segment consists of a double dot <tt>..</tt> | |||
followed by a child segment (using bracket notation).</t> | followed by a child segment (using bracket notation).</t> | |||
<t>Shortand notations are also provided that correspond to the short hand forms of the child segment.</t> | <t>Shorthand notations are also provided that correspond to the shor thand forms of the child segment.</t> | |||
<sourcecode type="abnf" name="jsonpath-collected.abnf"><![CDATA[ | <sourcecode type="abnf" name="jsonpath-collected.abnf"><![CDATA[ | |||
descendant-segment = ".." (bracketed-selection / | descendant-segment = ".." (bracketed-selection / | |||
wildcard-selector / | wildcard-selector / | |||
member-name-shorthand) | member-name-shorthand) | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t><tt>..*</tt>, the <tt>descendant-segment</tt> directly built from a | <t><tt>..*</tt>, the <tt>descendant-segment</tt> directly built from a | |||
<tt>wildcard-selector</tt>, is shorthand for <tt>..[*]</tt>.</t> | <tt>wildcard-selector</tt>, is shorthand for <tt>..[*]</tt>.</t> | |||
<t><tt>..<member-name></tt>, a <tt>descendant-segment</tt> bui lt from a | <t><tt>..<member-name></tt>, a <tt>descendant-segment</tt> bui lt from a | |||
<tt>member-name-shorthand</tt>, is shorthand for <tt>..['<member-name>']</ | <tt>member-name-shorthand</tt>, is shorthand for <tt>..&wj;['<member-name> | |||
tt>. | ']</tt>. | |||
Note: as with the similar shorthand of a <tt>child-segment</tt>, this can | Note: As with the similar shorthand of a <tt>child-segment</tt>, this can | |||
only be used with member names that are composed of certain | only be used with member names that are composed of certain | |||
characters, as specified in the ABNF rule <tt>member-name-shorthand</tt>.</t> | characters, as specified in the ABNF rule <tt>member-name-shorthand</tt>.</t> | |||
<t>Note: <tt>..</tt> on its own is not a valid segment.</t> | <t>Note: On its own, <tt>..</tt> is not a valid segment.</t> | |||
</section> | </section> | |||
<section anchor="semantics-7"> | <section anchor="semantics-7"> | |||
<name>Semantics</name> | <name>Semantics</name> | |||
<t>A descendant segment produces zero or more descendants of an inpu t value.</t> | <t>A descendant segment produces zero or more descendants of an inpu t value.</t> | |||
<t>For each node in the input nodelist, | <t>For each node in the input nodelist, | |||
a descendant selector visits the input node and each of | a descendant selector visits the input node and each of | |||
its descendants such that:</t> | its descendants such that:</t> | |||
<ul spacing="normal"> | <ul spacing="normal"> | |||
<li>nodes of any array are visited in array order, and</li> | <li>nodes of any array are visited in array order, and</li> | |||
<li>nodes are visited before their descendants.</li> | <li>nodes are visited before their descendants.</li> | |||
</ul> | </ul> | |||
<t>The order in which the children of an object are visited is not s tipulated, since | <t>The order in which the children of an object are visited is not s tipulated, since | |||
JSON objects are unordered.</t> | JSON objects are unordered.</t> | |||
<t>Suppose the descendant segment is of the form <tt>..[<selector | <t>Suppose the descendant segment is of the form <tt>..&wj;[<sele | |||
s>]</tt> (after converting any shorthand | ctors>]</tt> (after converting any shorthand | |||
form to bracket notation) | form to bracket notation), | |||
and the nodes, in the order visited, are <tt>D1</tt>, ..., <tt>Dn</tt> (where <t t>n >= 1</tt>). | and the nodes, in the order visited, are <tt>D1</tt>, ..., <tt>Dn</tt> (where <t t>n >= 1</tt>). | |||
Note: <tt>D1</tt> is the input value.</t> | Note: <tt>D1</tt> is the input value.</t> | |||
<t>For each <tt>i</tt> such that <tt>1 <= i <= n</tt>, the nod elist <tt>Ri</tt> is defined to be a result of applying | <t>For each <tt>i</tt> such that <tt>1 <= i <= n</tt>, the nod elist <tt>Ri</tt> is defined to be a result of applying | |||
the child segment <tt>[<selectors>]</tt> to the node <tt>Di</tt>.</t> | the child segment <tt>[<selectors>]</tt> to the node <tt>Di</tt>.</t> | |||
<t>For each node in the input nodelist, | <t>For each node in the input nodelist, | |||
the result of the descendant segment is the concatenation of <tt>R1</tt>, | the result of the descendant segment is the concatenation of <tt>R1</tt>, | |||
..., <tt>Rn</tt> (in that order). | ..., <tt>Rn</tt> (in that order). | |||
These results are then concatenated in input nodelist order to form | These results are then concatenated in input nodelist order to form | |||
the result of the segment.</t> | the result of the segment.</t> | |||
<t>So a descendant segment drills down one or more levels into the s tructure of each input value.</t> | <t>In summary, a descendant segment drills down one or more levels in to the structure of each input value.</t> | |||
</section> | </section> | |||
<section anchor="examples-8"> | <section anchor="examples-8"> | |||
<name>Examples</name> | <name>Examples</name> | |||
<t>JSON:</t> | <t>JSON:</t> | |||
<sourcecode type="json"><![CDATA[ | <sourcecode type="json"><![CDATA[ | |||
{ | { | |||
"o": {"j": 1, "k": 2}, | "o": {"j": 1, "k": 2}, | |||
"a": [5, 3, [{"j": 4}, {"k": 6}]] | "a": [5, 3, [{"j": 4}, {"k": 6}]] | |||
} | } | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t>Queries:</t> | <t>Queries:</t> | |||
<t>(Note that the fourth example can be expressed in two equivalent | <t>(Note that the fourth example can be expressed in two equivalent | |||
queries, shown here in one table row instead of two almost identical rows.)</t> | queries, shown in <xref target="tbl-descendant-segment"/> in one table row inste ad of two almost-identical rows.)</t> | |||
<table anchor="tbl-descendant-segment"> | <table anchor="tbl-descendant-segment"> | |||
<name>Descendant segment examples</name> | <name>Descendant Segment Examples</name> | |||
<thead> | <thead> | |||
<tr> | <tr> | |||
<th align="center">Query</th> | <th align="center">Query</th> | |||
<th align="left">Result</th> | <th align="left">Result</th> | |||
<th align="center">Result Paths</th> | <th align="center">Result Paths</th> | |||
<th align="left">Comment</th> | <th align="left">Comment</th> | |||
</tr> | </tr> | |||
</thead> | </thead> | |||
<tbody> | <tbody> | |||
<tr> | <tr> | |||
skipping to change at line 2667 ¶ | skipping to change at line 2641 ¶ | |||
<td align="center"> | <td align="center"> | |||
<tt>$.a..[0, 1]</tt></td> | <tt>$.a..[0, 1]</tt></td> | |||
<td align="left"> | <td align="left"> | |||
<tt>5</tt> <br/> <tt>3</tt> <br/> <tt>{"j": 4}</tt> <br/> <t t>{"k": 6}</tt></td> | <tt>5</tt> <br/> <tt>3</tt> <br/> <tt>{"j": 4}</tt> <br/> <t t>{"k": 6}</tt></td> | |||
<td align="center"> | <td align="center"> | |||
<tt>$['a'][0]</tt> <br/> <tt>$['a'][1]</tt> <br/> <tt>$['a'] [2][0]</tt> <br/> <tt>$['a'][2][1]</tt></td> | <tt>$['a'][0]</tt> <br/> <tt>$['a'][1]</tt> <br/> <tt>$['a'] [2][0]</tt> <br/> <tt>$['a'][2][1]</tt></td> | |||
<td align="left">Multiple segments</td> | <td align="left">Multiple segments</td> | |||
</tr> | </tr> | |||
</tbody> | </tbody> | |||
</table> | </table> | |||
<t>Note: the ordering of the results for the <tt>$..[*]</tt> and <tt >$..*</tt> examples above is not guaranteed, except that:</t> | <t>Note: The ordering of the results for the <tt>$..[*]</tt> and <tt >$..*</tt> examples above is not guaranteed, except that:</t> | |||
<ul spacing="normal"> | <ul spacing="normal"> | |||
<li> | <li> | |||
<tt>{"j": 1, "k": 2}</tt> must appear before <tt>1</tt> and <tt> 2</tt>,</li> | <tt>{"j": 1, "k": 2}</tt> must appear before <tt>1</tt> and <tt> 2</tt>,</li> | |||
<li> | <li> | |||
<tt>[5, 3, [{"j": 4}, {"k": 6}]]</tt> must appear before <tt>5</ tt>, <tt>3</tt>, and <tt>[{"j": 4}, {"k": 6}]</tt>,</li> | <tt>[5, 3, [{"j": 4}, {"k": 6}]]</tt> must appear before <tt>5</ tt>, <tt>3</tt>, and <tt>[{"j": 4}, {"k": 6}]</tt>,</li> | |||
<li> | <li> | |||
<tt>5</tt> must appear before <tt>3</tt> which must appear befor e <tt>[{"j": 4}, {"k": 6}]</tt>,</li> | <tt>5</tt> must appear before <tt>3</tt>, which must appear befo re <tt>[{"j": 4}, {"k": 6}]</tt>,</li> | |||
<li> | <li> | |||
<tt>5</tt> and <tt>3</tt> must appear before <tt>{"j": 4}</tt>, <tt>4</tt>, <tt>, {"k": 6}</tt>, and <tt>6</tt>,</li> | <tt>5</tt> and <tt>3</tt> must appear before <tt>{"j": 4}</tt>, <tt>4</tt>, <tt>{"k": 6}</tt>, and <tt>6</tt>,</li> | |||
<li> | <li> | |||
<tt>[{"j": 4}, {"k": 6}]</tt> must appear before <tt>{"j": 4}</t t> and <tt>{"k": 6}</tt>,</li> | <tt>[{"j": 4}, {"k": 6}]</tt> must appear before <tt>{"j": 4}</t t> and <tt>{"k": 6}</tt>,</li> | |||
<li> | <li> | |||
<tt>{"j": 4}</tt> must appear before <tt>{"k": 6}</tt>,</li> | <tt>{"j": 4}</tt> must appear before <tt>{"k": 6}</tt>,</li> | |||
<li> | <li> | |||
<tt>{"k": 6}</tt> must appear before <tt>4</tt>, and</li> | <tt>{"k": 6}</tt> must appear before <tt>4</tt>, and</li> | |||
<li> | <li> | |||
<tt>4</tt> must appear before <tt>6</tt>.</li> | <tt>4</tt> must appear before <tt>6</tt>.</li> | |||
</ul> | </ul> | |||
<t>The example above with the query <tt>$.o..[*, *]</tt> shows that a selector may produce nodelists in distinct orders | <t>The example above with the query <tt>$.o..[*, *]</tt> shows that a selector may produce nodelists in distinct orders | |||
each time it appears in the descendant segment.</t> | each time it appears in the descendant segment.</t> | |||
<t>The example above with the query <tt>$.a..[0, 1]</tt> shows that the child segment <tt>[0, 1]</tt> is applied to each node | <t>The example above with the query <tt>$.a..[0, 1]</tt> shows that the child segment <tt>[0, 1]</tt> is applied to each node | |||
in turn (rather than the nodes being visited once per selector, which is the cas e for some JSONPath implementations | in turn (rather than the nodes being visited once per selector, which is the cas e for some JSONPath implementations | |||
that do not conform to this specification).</t> | that do not conform to this specification).</t> | |||
</section> | </section> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="null-semantics"> | <section anchor="null-semantics"> | |||
<name>Semantics of <tt>null</tt></name> | <name>Semantics of <tt>null</tt></name> | |||
<t>Note: JSON <tt>null</tt> is treated the same as any other JSON value: it is not taken to mean "undefined" or "missing".</t> | <t>Note: JSON <tt>null</tt> is treated the same as any other JSON value, i.e., it is not taken to mean "undefined" or "missing".</t> | |||
<section anchor="examples-9"> | <section anchor="examples-9"> | |||
<name>Examples</name> | <name>Examples</name> | |||
<t>JSON:</t> | <t>JSON:</t> | |||
<sourcecode type="json"><![CDATA[ | <sourcecode type="json"><![CDATA[ | |||
{"a": null, "b": [null], "c": [{}], "null": 1} | {"a": null, "b": [null], "c": [{}], "null": 1} | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t>Queries:</t> | <t>Queries:</t> | |||
<table anchor="tbl-null-examples"> | <table anchor="tbl-null-examples"> | |||
<name>Examples involving (or not involving) null</name> | <name>Examples Involving (or Not Involving) <tt>null</tt></name> | |||
<thead> | <thead> | |||
<tr> | <tr> | |||
<th align="center">Query</th> | <th align="center">Query</th> | |||
<th align="left">Result</th> | <th align="left">Result</th> | |||
<th align="center">Result Paths</th> | <th align="center">Result Paths</th> | |||
<th align="left">Comment</th> | <th align="left">Comment</th> | |||
</tr> | </tr> | |||
</thead> | </thead> | |||
<tbody> | <tbody> | |||
<tr> | <tr> | |||
skipping to change at line 2727 ¶ | skipping to change at line 2701 ¶ | |||
<tt>$.a</tt></td> | <tt>$.a</tt></td> | |||
<td align="left"> | <td align="left"> | |||
<tt>null</tt></td> | <tt>null</tt></td> | |||
<td align="center"> | <td align="center"> | |||
<tt>$['a']</tt></td> | <tt>$['a']</tt></td> | |||
<td align="left">Object value</td> | <td align="left">Object value</td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="center"> | <td align="center"> | |||
<tt>$.a[0]</tt></td> | <tt>$.a[0]</tt></td> | |||
<td align="left"> </td> | <td align="left"> </td> | |||
<td align="center"> </td> | <td align="center"> </td> | |||
<td align="left"> | <td align="left"> | |||
<tt>null</tt> used as array</td> | <tt>null</tt> used as array</td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="center"> | <td align="center"> | |||
<tt>$.a.d</tt></td> | <tt>$.a.d</tt></td> | |||
<td align="left"> </td> | <td align="left"> </td> | |||
<td align="center"> </td> | <td align="center"> </td> | |||
<td align="left"> | <td align="left"> | |||
<tt>null</tt> used as object</td> | <tt>null</tt> used as object</td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="center"> | <td align="center"> | |||
<tt>$.b[0]</tt></td> | <tt>$.b[0]</tt></td> | |||
<td align="left"> | <td align="left"> | |||
<tt>null</tt></td> | <tt>null</tt></td> | |||
<td align="center"> | <td align="center"> | |||
<tt>$['b'][0]</tt></td> | <tt>$['b'][0]</tt></td> | |||
skipping to change at line 2779 ¶ | skipping to change at line 2753 ¶ | |||
<tt>$.b[?@==null]</tt></td> | <tt>$.b[?@==null]</tt></td> | |||
<td align="left"> | <td align="left"> | |||
<tt>null</tt></td> | <tt>null</tt></td> | |||
<td align="center"> | <td align="center"> | |||
<tt>$['b'][0]</tt></td> | <tt>$['b'][0]</tt></td> | |||
<td align="left">Comparison</td> | <td align="left">Comparison</td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="center"> | <td align="center"> | |||
<tt>$.c[?@.d==null]</tt></td> | <tt>$.c[?@.d==null]</tt></td> | |||
<td align="left"> </td> | <td align="left"> </td> | |||
<td align="center"> </td> | <td align="center"> </td> | |||
<td align="left">Comparison with "missing" value</td> | <td align="left">Comparison with "missing" value</td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="center"> | <td align="center"> | |||
<tt>$.null</tt></td> | <tt>$.null</tt></td> | |||
<td align="left"> | <td align="left"> | |||
<tt>1</tt></td> | <tt>1</tt></td> | |||
<td align="center"> | <td align="center"> | |||
<tt>$['null']</tt></td> | <tt>$['null']</tt></td> | |||
<td align="left">Not JSON null at all, just a member name string </td> | <td align="left">Not JSON <tt>null</tt> at all, just a member na me string</td> | |||
</tr> | </tr> | |||
</tbody> | </tbody> | |||
</table> | </table> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="normalized-paths"> | <section anchor="normalized-paths"> | |||
<name>Normalized Paths</name> | <name>Normalized Paths</name> | |||
<t>A Normalized Path is a unique representation of the location of a nod e in a value which | <t>A Normalized Path is a unique representation of the location of a nod e in a value that | |||
uniquely identifies the node in the value. | uniquely identifies the node in the value. | |||
Specifically, a Normalized Path is a JSONPath query with restricted syntax (defi ned below), | Specifically, a Normalized Path is a JSONPath query with restricted syntax (defi ned below), | |||
e.g., <tt>$['book'][3]</tt>, which when applied to the value results in a nodeli st consisting | e.g., <tt>$['book'][3]</tt>, which when applied to the value, results in a nodel ist consisting | |||
of just the node identified by the Normalized Path. | of just the node identified by the Normalized Path. | |||
Note: a Normalized Path represents the identity of a node <em>in a specific valu e</em>. | Note: A Normalized Path represents the identity of a node <em>in a specific valu e</em>. | |||
There is precisely one Normalized Path identifying any particular node in a valu e.</t> | There is precisely one Normalized Path identifying any particular node in a valu e.</t> | |||
<t>A nodelist may be represented compactly in JSON as an array of string s, where the strings are | <t>A nodelist may be represented compactly in JSON as an array of string s, where the strings are | |||
Normalized Paths.</t> | Normalized Paths.</t> | |||
<t>Normalized Paths provide a predictable format that simplifies testing and post-processing | <t>Normalized Paths provide a predictable format that simplifies testing and post-processing | |||
of nodelists, e.g., to remove duplicate nodes. | of nodelists, e.g., to remove duplicate nodes. | |||
Normalized Paths are used in this document as result paths in examples.</t> | Normalized Paths are used in this document as result paths in examples.</t> | |||
<t>Normalized Paths use the canonical bracket notation, rather than dot notation.</t> | <t>Normalized Paths use the canonical bracket notation, rather than dot notation.</t> | |||
<t>Single quotes are used in Normalized Paths to delimit string member n ames. This reduces the | <t>Single quotes are used in Normalized Paths to delimit string member n ames. This reduces the | |||
number of characters that need escaping when Normalized Paths appear in double q | number of characters that need escaping when Normalized Paths appear in | |||
uote-delimited | strings delimited by double quotes, e.g., in JSON texts.</t> | |||
strings, e.g., in JSON texts.</t> | <t>Certain characters are escaped in Normalized Paths in one and only on | |||
<t>Certain characters are escaped in Normalized Paths, in one and only o | e way; all other | |||
ne way; all other | characters are unescaped.</t> | |||
characters are unescaped.</t> | <aside> | |||
<t>Note: Normalized Paths are singular queries, but not all singular que ries are Normalized Paths. | <t>Note: Normalized Paths are singular queries, but not all singular que ries are Normalized Paths. | |||
For example, <tt>$[-3]</tt> is a singular query, but is not a Normalized Path. | For example, <tt>$[-3]</tt> is a singular query but is not a Normalized Path. | |||
The Normalized Path equivalent to <tt>$[-3]</tt> would have an index equal to th e array length minus <tt>3</tt>. | The Normalized Path equivalent to <tt>$[-3]</tt> would have an index equal to th e array length minus <tt>3</tt>. | |||
(The array length must be at least <tt>3</tt> if <tt>$[-3]</tt> is to identify a | (The array length must be at least <tt>3</tt> if <tt>$[-3]</tt> is to ide | |||
node.)</t> | ntify a node.)</t> | |||
</aside> | ||||
<sourcecode type="abnf" name="normalized-path-collected.abnf"><![CDATA[ | <sourcecode type="abnf" name="normalized-path-collected.abnf"><![CDATA[ | |||
normalized-path = root-identifier *(normal-index-segment) | normalized-path = root-identifier *(normal-index-segment) | |||
normal-index-segment = "[" normal-selector "]" | normal-index-segment = "[" normal-selector "]" | |||
normal-selector = normal-name-selector / normal-index-selector | normal-selector = normal-name-selector / normal-index-selector | |||
normal-name-selector = %x27 *normal-single-quoted %x27 ; 'string' | normal-name-selector = %x27 *normal-single-quoted %x27 ; 'string' | |||
normal-single-quoted = normal-unescaped / | normal-single-quoted = normal-unescaped / | |||
ESC normal-escapable | ESC normal-escapable | |||
normal-unescaped = ; omit %x0-1F control codes | normal-unescaped = ; omit %x0-1F control codes | |||
%x20-26 / | %x20-26 / | |||
; omit 0x27 ' | ; omit 0x27 ' | |||
%x28-5B / | %x28-5B / | |||
; omit 0x5C \ | ; omit 0x5C \ | |||
%x5D-D7FF / ; skip surrogate code points | %x5D-D7FF / | |||
; skip surrogate code points | ||||
%xE000-10FFFF | %xE000-10FFFF | |||
normal-escapable = %x62 / ; b BS backspace U+0008 | normal-escapable = %x62 / ; b BS backspace U+0008 | |||
%x66 / ; f FF form feed U+000C | %x66 / ; f FF form feed U+000C | |||
%x6E / ; n LF line feed U+000A | %x6E / ; n LF line feed U+000A | |||
%x72 / ; r CR carriage return U+000D | %x72 / ; r CR carriage return U+000D | |||
%x74 / ; t HT horizontal tab U+0009 | %x74 / ; t HT horizontal tab U+0009 | |||
"'" / ; ' apostrophe U+0027 | "'" / ; ' apostrophe U+0027 | |||
"\" / ; \ backslash (reverse solidus) U+005C | "\" / ; \ backslash (reverse solidus) U+005C | |||
(%x75 normal-hexchar) | (%x75 normal-hexchar) | |||
; certain values u00xx U+00XX | ; certain values u00xx U+00XX | |||
normal-hexchar = "0" "0" | normal-hexchar = "0" "0" | |||
( | ( | |||
("0" %x30-37) / ; "00"-"07" | ("0" %x30-37) / ; "00"-"07" | |||
; omit U+0008-U+000A BS HT LF | ; omit U+0008-U+000A BS HT LF | |||
("0" %x62) / ; "0b" | ("0" %x62) / ; "0b" | |||
; omit U+000C-U+000D FF CR | ; omit U+000C-U+000D FF CR | |||
("0" %x65-66) / ; "0e"-"0f" | ("0" %x65-66) / ; "0e"-"0f" | |||
("1" normal-HEXDIG) | ("1" normal-HEXDIG) | |||
) | ) | |||
normal-HEXDIG = DIGIT / %x61-66 ; "0"-"9", "a"-"f" | normal-HEXDIG = DIGIT / %x61-66 ; "0"-"9", "a"-"f" | |||
normal-index-selector = "0" / (DIGIT1 *DIGIT) | normal-index-selector = "0" / (DIGIT1 *DIGIT) | |||
; non-negative decimal integer | ; non-negative decimal integer | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t>Since there can only be one Normalized Path identifying a given node, the syntax | <t>Since there can only be one Normalized Path identifying a given node, the syntax | |||
stipulates which characters are escaped and which are not. | stipulates which characters are escaped and which are not. | |||
So the definition of <tt>normal-hexchar</tt> is designed for hex escaping of cha racters | So the definition of <tt>normal-hexchar</tt> is designed for hex escaping of cha racters | |||
which are not straightforwardly printable, for example U+000B LINE TABULATION, b ut | that are not straightforwardly printable, for example, U+000B LINE TABULATION, b ut | |||
for which no standard JSON escape, such as <tt>\n</tt>, is available.</t> | for which no standard JSON escape, such as <tt>\n</tt>, is available.</t> | |||
<section anchor="examples-10"> | <section anchor="examples-10"> | |||
<name>Examples</name> | <name>Examples</name> | |||
<table anchor="tbl-normalized-path-examples"> | <table anchor="tbl-normalized-path-examples"> | |||
<name>Normalized Path examples</name> | <name>Normalized Path Examples</name> | |||
<thead> | <thead> | |||
<tr> | <tr> | |||
<th align="center">Path</th> | <th align="center">Path</th> | |||
<th align="center">Normalized Path</th> | <th align="center">Normalized Path</th> | |||
<th align="left">Comment</th> | <th align="left">Comment</th> | |||
</tr> | </tr> | |||
</thead> | </thead> | |||
<tbody> | <tbody> | |||
<tr> | <tr> | |||
<td align="center"> | <td align="center"> | |||
skipping to change at line 2922 ¶ | skipping to change at line 2899 ¶ | |||
<td align="center"> | <td align="center"> | |||
<tt>$['a']</tt></td> | <tt>$['a']</tt></td> | |||
<td align="left">Unicode character</td> | <td align="left">Unicode character</td> | |||
</tr> | </tr> | |||
</tbody> | </tbody> | |||
</table> | </table> | |||
</section> | </section> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="IANA"> | <section anchor="IANA"> | |||
<name>IANA Considerations</name> | <name>IANA Considerations</name> | |||
<t><cref anchor="replace-xxxx">RFC Ed.: throughout this section, please re | ||||
place | ||||
RFCXXXX with the RFC number of this specification and remove this | ||||
note.</cref></t> | ||||
<section anchor="registration-of-media-type-applicationjsonpath"> | <section anchor="registration-of-media-type-applicationjsonpath"> | |||
<name>Registration of Media Type application/jsonpath</name> | <name>Registration of Media Type application/jsonpath</name> | |||
<t>IANA is requested to register the following media type <xref target=" RFC6838"/>:</t> | <t>IANA has registered the following media type <xref target="RFC6838"/> :</t> | |||
<dl> | <dl> | |||
<dt>Type name:</dt> | <dt>Type name:</dt> | |||
<dd> | <dd> | |||
<t>application</t> | <t>application</t> | |||
</dd> | </dd> | |||
<dt>Subtype name:</dt> | <dt>Subtype name:</dt> | |||
<dd> | <dd> | |||
<t>jsonpath</t> | <t>jsonpath</t> | |||
</dd> | </dd> | |||
<dt>Required parameters:</dt> | <dt>Required parameters:</dt> | |||
skipping to change at line 2952 ¶ | skipping to change at line 2927 ¶ | |||
<dt>Optional parameters:</dt> | <dt>Optional parameters:</dt> | |||
<dd> | <dd> | |||
<t>N/A</t> | <t>N/A</t> | |||
</dd> | </dd> | |||
<dt>Encoding considerations:</dt> | <dt>Encoding considerations:</dt> | |||
<dd> | <dd> | |||
<t>binary (UTF-8)</t> | <t>binary (UTF-8)</t> | |||
</dd> | </dd> | |||
<dt>Security considerations:</dt> | <dt>Security considerations:</dt> | |||
<dd> | <dd> | |||
<t>See the Security Considerations section of RFCXXXX.</t> | <t>See the Security Considerations section of RFC 9535.</t> | |||
</dd> | </dd> | |||
<dt>Interoperability considerations:</dt> | <dt>Interoperability considerations:</dt> | |||
<dd> | <dd> | |||
<t>N/A</t> | <t>N/A</t> | |||
</dd> | </dd> | |||
<dt>Published specification:</dt> | <dt>Published specification:</dt> | |||
<dd> | <dd> | |||
<t>RFCXXXX</t> | <t>RFC 9535</t> | |||
</dd> | </dd> | |||
<dt>Applications that use this media type:</dt> | <dt>Applications that use this media type:</dt> | |||
<dd> | <dd> | |||
<t>Applications that need to convey queries in JSON data</t> | <t>Applications that need to convey queries in JSON data</t> | |||
</dd> | </dd> | |||
<dt>Fragment identifier considerations:</dt> | <dt>Fragment identifier considerations:</dt> | |||
<dd> | <dd> | |||
<t>N/A</t> | <t>N/A</t> | |||
</dd> | </dd> | |||
<dt>Additional information:</dt> | <dt>Additional information:</dt> | |||
<dd> | <dd><t><br/></t> | |||
<dl> | <dl spacing="compact"> | |||
<dt>Deprecated alias names for this type:</dt> | <dt>Deprecated alias names for this type:</dt> | |||
<dd> | <dd> | |||
<t>N/A</t> | <t>N/A</t> | |||
</dd> | </dd> | |||
<dt>Magic number(s):</dt> | <dt>Magic number(s):</dt> | |||
<dd> | <dd> | |||
<t>N/A</t> | <t>N/A</t> | |||
</dd> | </dd> | |||
<dt>File extension(s):</dt> | <dt>File extension(s):</dt> | |||
<dd> | <dd> | |||
<t>N/A</t> | <t>N/A</t> | |||
</dd> | </dd> | |||
<dt>Macintosh file type code(s):</dt> | <dt>Macintosh file type code(s):</dt> | |||
<dd> | <dd> | |||
<t>N/A</t> | <t>N/A</t> | |||
</dd> | </dd> | |||
</dl> | </dl> | |||
</dd> | </dd> | |||
</dl> | <dt>Person & email address to contact for further information:</dt> | |||
<t>Person & email address to contact for further information: | <dd>iesg@ietf.org</dd> | |||
iesg@ietf.org</t> | ||||
<dl> | ||||
<dt>Intended usage:</dt> | <dt>Intended usage:</dt> | |||
<dd> | <dd> | |||
<t>COMMON</t> | <t>COMMON</t> | |||
</dd> | </dd> | |||
<dt>Restrictions on usage:</dt> | <dt>Restrictions on usage:</dt> | |||
<dd> | <dd> | |||
<t>N/A</t> | <t>N/A</t> | |||
</dd> | </dd> | |||
<dt>Author:</dt> | <dt>Author:</dt> | |||
<dd> | <dd> | |||
<t>JSONPath WG</t> | <t>JSONPath WG</t> | |||
</dd> | </dd> | |||
<dt>Change controller:</dt> | <dt>Change controller:</dt> | |||
<dd> | <dd> | |||
<t>IETF</t> | <t>IETF</t> | |||
</dd> | </dd> | |||
<dt>Provisional registration? (standards tree only):</dt> | ||||
<dd> | ||||
<t>no</t> | ||||
</dd> | ||||
</dl> | </dl> | |||
</section> | </section> | |||
<section anchor="iana-fnex"> | <section anchor="iana-fnex"> | |||
<name>Function Extensions</name> | <name>Function Extensions Subregistry</name> | |||
<t>This specification defines a new "Function Extensions sub-registry" i | <t>Per this specification, IANA has created a new "Function Extensions" | |||
n | subregistry in | |||
a new "JSONPath Parameters registry", with the policy "expert review" | a new "JSONPath" registry. The "Function Extensions" subregistry has the policy | |||
(<xref section="4.5" sectionFormat="of" target="BCP26"/>).</t> | "Expert Review" | |||
(<xref section="4.5" sectionFormat="of" target="RFC8126"></xref>).</t> | ||||
<t anchor="de-instructions">The experts are instructed to be frugal in t he allocation of function | <t anchor="de-instructions">The experts are instructed to be frugal in t he allocation of function | |||
extension names that are suggestive of generally applicable semantics, | extension names that are suggestive of generally applicable semantics, | |||
keeping them in reserve for functions that are likely to enjoy wide | keeping them in reserve for functions that are likely to enjoy wide | |||
use and can make good use of their conciseness. | use and can make good use of their conciseness. | |||
The expert is also instructed to direct the registrant to provide a | The expert is also instructed to direct the registrant to provide a | |||
specification (<xref section="4.6" sectionFormat="of" target="BCP26"/>), but can | specification (<xref section="4.6" sectionFormat="of" target="RFC8126"></xref>) | |||
make exceptions, | but can make exceptions, | |||
for instance when a specification is not available at the time of | for instance, when a specification is not available at the time of | |||
registration but is likely forthcoming. | registration but is likely forthcoming. | |||
If the expert becomes aware of function extensions that are deployed and | If the expert becomes aware of function extensions that are deployed and | |||
in use, they may also initiate a registration on their own if | in use, they may also initiate a registration on their own if | |||
they deem such a registration can avert potential future collisions.</t> | they deem such a registration can avert potential future collisions.</t> | |||
<t>Each entry in the sub-registry must include:</t> | <t>Each entry in the subregistry must include the following:</t> | |||
<dl newline="true"> | <dl newline="true"> | |||
<dt>Function Name:</dt> | <dt>Function Name:</dt> | |||
<dd> | <dd> | |||
<t>a lower case ASCII <xref target="STD80"/> string that starts with | <t>A lowercase ASCII <xref target="RFC0020"/> string that starts wit | |||
a letter and can | h a letter and can | |||
contain letters, digits and underscore characters afterwards | contain letters, digits, and underscore characters afterwards | |||
(<tt>[a-z][_a-z0-9]*</tt>). No other entry in the sub-registry can have the | (<tt>[a-z][_a-z0-9]*</tt>). No other entry in the subregistry can have the | |||
same function name.</t> | same function name.</t> | |||
</dd> | </dd> | |||
<dt>Brief description:</dt> | <dt>Brief description:</dt> | |||
<dd> | <dd> | |||
<t>a brief description</t> | <t>A brief description</t> | |||
</dd> | </dd> | |||
<dt>Parameters:</dt> | <dt>Parameters:</dt> | |||
<dd> | <dd> | |||
<t>A comma-separated list of zero or more declared types, one for ea ch of the | <t>A comma-separated list of zero or more declared types, one for ea ch of the | |||
arguments expected for this function extension</t> | arguments expected for this function extension</t> | |||
</dd> | </dd> | |||
<dt>Result:</dt> | <dt>Result:</dt> | |||
<dd> | <dd> | |||
<t>The declared type of the result for this function extension</t> | <t>The declared type of the result for this function extension</t> | |||
</dd> | </dd> | |||
<dt>Change Controller:</dt> | <dt>Change Controller:</dt> | |||
<dd> | <dd> | |||
<t>(see <xref section="2.3" sectionFormat="of" target="BCP26"/>)</t> | <t>See <xref section="2.3" sectionFormat="of" target="RFC8126"></xre f>.</t> | |||
</dd> | </dd> | |||
<dt>Reference:</dt> | <dt>Reference:</dt> | |||
<dd> | <dd> | |||
<t>a reference document that provides a description of the function | <t>A reference document that provides a description of the function | |||
extension</t> | extension</t> | |||
</dd> | </dd> | |||
</dl> | </dl> | |||
<t>Initial entries in this sub-registry are as listed in <xref target="p | <t>The initial entries in this subregistry are listed in <xref target="p | |||
re-reg"/>; the | re-reg"/>; the | |||
entries in the Column "Change Controller" all have the value "IETF" | entries in the "Change Controller" column all have the value "IETF", | |||
and the entries in the column | and the entries in the | |||
"Reference" all have the value "<xref target="fnex"/> of RFCXXXX":</t> | "Reference" column all have the value "<xref target="fnex"/> of RFC 9535":</t> | |||
<table anchor="pre-reg"> | <table anchor="pre-reg"> | |||
<name>Initial Entries in the Function Extensions Subregistry</name> | <name>Initial Entries in the Function Extensions Subregistry</name> | |||
<thead> | <thead> | |||
<tr> | <tr> | |||
<th align="left">Function Name</th> | <th align="left">Function Name</th> | |||
<th align="left">Brief description</th> | <th align="left">Brief Description</th> | |||
<th align="left">Parameters</th> | <th align="left">Parameters</th> | |||
<th align="left">Result</th> | <th align="left">Result</th> | |||
</tr> | </tr> | |||
</thead> | </thead> | |||
<tbody> | <tbody> | |||
<tr> | <tr> | |||
<td align="left">length</td> | <td align="left">length</td> | |||
<td align="left">length of string, array, object</td> | <td align="left">length of string, array, or object</td> | |||
<td align="left"> | <td align="left"> | |||
<tt>ValueType</tt></td> | <tt>ValueType</tt></td> | |||
<td align="left"> | <td align="left"> | |||
<tt>ValueType</tt></td> | <tt>ValueType</tt></td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="left">count</td> | <td align="left">count</td> | |||
<td align="left">size of nodelist</td> | <td align="left">size of nodelist</td> | |||
<td align="left"> | <td align="left"> | |||
<tt>NodesType</tt></td> | <tt>NodesType</tt></td> | |||
skipping to change at line 3114 ¶ | skipping to change at line 3083 ¶ | |||
<tr> | <tr> | |||
<td align="left">search</td> | <td align="left">search</td> | |||
<td align="left">regular expression substring match</td> | <td align="left">regular expression substring match</td> | |||
<td align="left"> | <td align="left"> | |||
<tt>ValueType</tt>, <tt>ValueType</tt></td> | <tt>ValueType</tt>, <tt>ValueType</tt></td> | |||
<td align="left"> | <td align="left"> | |||
<tt>LogicalType</tt></td> | <tt>LogicalType</tt></td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="left">value</td> | <td align="left">value</td> | |||
<td align="left">value of single node in nodelist</td> | <td align="left">value of the single node in nodelist</td> | |||
<td align="left"> | <td align="left"> | |||
<tt>NodesType</tt></td> | <tt>NodesType</tt></td> | |||
<td align="left"> | <td align="left"> | |||
<tt>ValueType</tt></td> | <tt>ValueType</tt></td> | |||
</tr> | </tr> | |||
</tbody> | </tbody> | |||
</table> | </table> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="Security"> | <section anchor="Security"> | |||
<name>Security Considerations</name> | <name>Security Considerations</name> | |||
<t>Security considerations for JSONPath can stem from</t> | <t>Security considerations for JSONPath can stem from:</t> | |||
<ul spacing="normal"> | <ul spacing="normal"> | |||
<li>attack vectors on JSONPath implementations,</li> | <li>attack vectors on JSONPath implementations,</li> | |||
<li>attack vectors on how JSONPath queries are formed, and</li> | <li>attack vectors on how JSONPath queries are formed, and</li> | |||
<li>the way JSONPath is used in security-relevant mechanisms.</li> | <li>the way JSONPath is used in security-relevant mechanisms.</li> | |||
</ul> | </ul> | |||
<section anchor="attack-vectors-on-jsonpath-implementations"> | <section anchor="attack-vectors-on-jsonpath-implementations"> | |||
<name>Attack Vectors on JSONPath Implementations</name> | <name>Attack Vectors on JSONPath Implementations</name> | |||
<t>Historically, JSONPath has often been implemented by feeding parts of | <t>Historically, JSONPath has often been implemented by feeding parts of | |||
the query to an underlying programming language engine, e.g., | the query to an underlying programming language engine, e.g., | |||
JavaScript's <tt>eval()</tt> function. | JavaScript's <tt>eval()</tt> function. | |||
This approach is well known to lead to injection attacks and would | This approach is well known to lead to injection attacks and would | |||
require perfect input validation to prevent these attacks (see | require perfect input validation to prevent these attacks (see | |||
<xref section="12" sectionFormat="of" target="RFC8259"/> for similar considerati ons for JSON itself). | <xref section="12" sectionFormat="of" target="RFC8259"/> for similar considerati ons for JSON itself). | |||
Instead, JSONPath implementations need to implement the entire syntax | Instead, JSONPath implementations need to implement the entire syntax | |||
of the query without relying on the parsers of programming language | of the query without relying on the parsers of programming language | |||
engines.</t> | engines.</t> | |||
<t>Attacks on availability may attempt to trigger unusually expensive | <t>Attacks on availability may attempt to trigger unusually expensive | |||
runtime performance exhibited by certain implementations in certain | runtime performance exhibited by certain implementations in certain | |||
cases. | cases. | |||
(See <xref section="10" sectionFormat="of" target="RFC8949"/> for issues in hash | (See <xref section="10" sectionFormat="of" target="RFC8949"/> for issues in hash | |||
-table implementations, | -table implementations | |||
and <xref section="8" sectionFormat="of" target="I-D.draft-ietf-jsonpath-iregexp | and <xref section="8" sectionFormat="of" target="RFC9485"/> for performance issu | |||
"/> for performance issues in regular | es in regular | |||
expression implementations.) | expression implementations.) | |||
Implementers need to be aware that good average performance is not | Implementers need to be aware that good average performance is not | |||
sufficient as long as an attacker can choose to submit specially | sufficient as long as an attacker can choose to submit specially | |||
crafted JSONPath queries or query arguments that trigger surprisingly high, poss ibly | crafted JSONPath queries or query arguments that trigger surprisingly high, poss ibly | |||
exponential, CPU usage or, for example via a naive recursive implementation of t he descendant segment, | exponential, CPU usage or, for example, via a naive recursive implementation of the descendant segment, | |||
stack overflow. Implementations need to have appropriate resource management | stack overflow. Implementations need to have appropriate resource management | |||
to mitigate these attacks.</t> | to mitigate these attacks.</t> | |||
</section> | </section> | |||
<section anchor="attack-vectors-on-how-jsonpath-queries-are-formed"> | <section anchor="attack-vectors-on-how-jsonpath-queries-are-formed"> | |||
<name>Attack Vectors on How JSONPath Queries are Formed</name> | <name>Attack Vectors on How JSONPath Queries Are Formed</name> | |||
<t>JSONPath queries are often not static, but formed from variables that | <t>JSONPath queries are often not static but formed from variables that | |||
provide index values, member names, or values to compare with in a | provide index values, member names, or values to compare with in a | |||
filter expression. | filter expression. | |||
These variables need to be validated (e.g., only allowing specific constructs | These variables need to be validated (e.g., only allowing specific constructs | |||
such as .name to be formed when the given values allow that) and translated | such as .name to be formed when the given values allow that) and translated | |||
(e.g., by escaping string delimiters). | (e.g., by escaping string delimiters). | |||
Not performing these validations and translations correctly can lead to unexpect ed | Not performing these validations and translations correctly can lead to unexpect ed | |||
failures, which can lead to Availability, Confidentiality, and | failures, which can lead to availability, confidentiality, and | |||
Integrity breaches, in particular if an adversary has control over the | integrity breaches, in particular, if an adversary has control over the | |||
values (e.g., by entering them into a Web form). | values (e.g., by entering them into a web form). | |||
The resulting class of attacks, <em>injections</em> (e.g., SQL injections), | The resulting class of attacks, <em>injections</em> (e.g., SQL injections), | |||
is consistently found among the top causes of application security | is consistently found among the top causes of application security | |||
vulnerabilities and requires particular attention.</t> | vulnerabilities and requires particular attention.</t> | |||
</section> | </section> | |||
<section anchor="attacks-on-security-mechanisms-that-employ-jsonpath"> | <section anchor="attacks-on-security-mechanisms-that-employ-jsonpath"> | |||
<name>Attacks on Security Mechanisms that Employ JSONPath</name> | <name>Attacks on Security Mechanisms That Employ JSONPath</name> | |||
<t>Where JSONPath is used as a part of a security mechanism, attackers | <t>Where JSONPath is used as a part of a security mechanism, attackers | |||
can attempt to provoke unexpected or unpredictable behavior, or | can attempt to provoke unexpected or unpredictable behavior or | |||
take advantage of differences in behavior between JSONPath implementations.</t> | take advantage of differences in behavior between JSONPath implementations.</t> | |||
<t>Unexpected or unpredictable behavior can arise from a query argument with certain | <t>Unexpected or unpredictable behavior can arise from a query argument with certain | |||
constructs described as unpredictable by <xref target="RFC8259"/>. | constructs described as unpredictable by <xref target="RFC8259"/>. | |||
Predictable behavior can be expected, except in relation to the ordering | Predictable behavior can be expected, except in relation to the ordering | |||
of objects, for any query argument conforming with <xref target="RFC7493"/>.</t> | of objects, for any query argument conforming with <xref target="RFC7493"/>.</t> | |||
<t>Other attacks can target the behavior of underlying technologies such as UTF-8 (see | <t>Other attacks can target the behavior of underlying technologies, suc h as UTF-8 (see | |||
<xref section="10" sectionFormat="of" target="RFC3629"/>) and the Unicode charac ter set.</t> | <xref section="10" sectionFormat="of" target="RFC3629"/>) and the Unicode charac ter set.</t> | |||
</section> | </section> | |||
</section> | </section> | |||
</middle> | </middle> | |||
<back> | <back> | |||
<references> | <references> | |||
<name>References</name> | <name>References</name> | |||
<references anchor="sec-normative-references"> | <references anchor="sec-normative-references"> | |||
<name>Normative References</name> | <name>Normative References</name> | |||
<reference anchor="STD80"> | ||||
<front> | ||||
<title>ASCII format for network interchange</title> | ||||
<author fullname="V.G. Cerf" initials="V.G." surname="Cerf"/> | ||||
<date month="October" year="1969"/> | ||||
</front> | ||||
<seriesInfo name="STD" value="80"/> | ||||
<seriesInfo name="RFC" value="20"/> | ||||
<seriesInfo name="DOI" value="10.17487/RFC0020"/> | ||||
</reference> | ||||
<reference anchor="BCP26"> | ||||
<front> | ||||
<title>Guidelines for Writing an IANA Considerations Section in RFCs | ||||
</title> | ||||
<author fullname="M. Cotton" initials="M." surname="Cotton"/> | ||||
<author fullname="B. Leiba" initials="B." surname="Leiba"/> | ||||
<author fullname="T. Narten" initials="T." surname="Narten"/> | ||||
<date month="June" year="2017"/> | ||||
<abstract> | ||||
<t>Many protocols make use of points of extensibility that use con | ||||
stants to identify various protocol parameters. To ensure that the values in the | ||||
se fields do not have conflicting uses and to promote interoperability, their al | ||||
locations are often coordinated by a central record keeper. For IETF protocols, | ||||
that role is filled by the Internet Assigned Numbers Authority (IANA).</t> | ||||
<t>To make assignments in a given registry prudently, guidance des | ||||
cribing the conditions under which new values should be assigned, as well as whe | ||||
n and how modifications to existing values can be made, is needed. This document | ||||
defines a framework for the documentation of these guidelines by specification | ||||
authors, in order to assure that the provided guidance for the IANA Consideratio | ||||
ns is clear and addresses the various issues that are likely in the operation of | ||||
a registry.</t> | ||||
<t>This is the third edition of this document; it obsoletes RFC 52 | ||||
26.</t> | ||||
</abstract> | ||||
</front> | ||||
<seriesInfo name="BCP" value="26"/> | ||||
<seriesInfo name="RFC" value="8126"/> | ||||
<seriesInfo name="DOI" value="10.17487/RFC8126"/> | ||||
</reference> | ||||
<reference anchor="RFC3629"> | ||||
<front> | ||||
<title>UTF-8, a transformation format of ISO 10646</title> | ||||
<author fullname="F. Yergeau" initials="F." surname="Yergeau"/> | ||||
<date month="November" year="2003"/> | ||||
<abstract> | ||||
<t>ISO/IEC 10646-1 defines a large character set called the Univer | ||||
sal Character Set (UCS) which encompasses most of the world's writing systems. T | ||||
he originally proposed encodings of the UCS, however, were not compatible with m | ||||
any current applications and protocols, and this has led to the development of U | ||||
TF-8, the object of this memo. UTF-8 has the characteristic of preserving the fu | ||||
ll US-ASCII range, providing compatibility with file systems, parsers and other | ||||
software that rely on US-ASCII values but are transparent to other values. This | ||||
memo obsoletes and replaces RFC 2279.</t> | ||||
</abstract> | ||||
</front> | ||||
<seriesInfo name="STD" value="63"/> | ||||
<seriesInfo name="RFC" value="3629"/> | ||||
<seriesInfo name="DOI" value="10.17487/RFC3629"/> | ||||
</reference> | ||||
<reference anchor="RFC5234"> | ||||
<front> | ||||
<title>Augmented BNF for Syntax Specifications: ABNF</title> | ||||
<author fullname="D. Crocker" initials="D." role="editor" surname="C | ||||
rocker"/> | ||||
<author fullname="P. Overell" initials="P." surname="Overell"/> | ||||
<date month="January" year="2008"/> | ||||
<abstract> | ||||
<t>Internet technical specifications often need to define a formal | ||||
syntax. Over the years, a modified version of Backus-Naur Form (BNF), called Au | ||||
gmented BNF (ABNF), has been popular among many Internet specifications. The cur | ||||
rent specification documents ABNF. It balances compactness and simplicity with r | ||||
easonable representational power. The differences between standard BNF and ABNF | ||||
involve naming rules, repetition, alternatives, order-independence, and value ra | ||||
nges. This specification also supplies additional rule definitions and encoding | ||||
for a core lexical analyzer of the type common to several Internet specification | ||||
s. [STANDARDS-TRACK]</t> | ||||
</abstract> | ||||
</front> | ||||
<seriesInfo name="STD" value="68"/> | ||||
<seriesInfo name="RFC" value="5234"/> | ||||
<seriesInfo name="DOI" value="10.17487/RFC5234"/> | ||||
</reference> | ||||
<reference anchor="RFC8259"> | ||||
<front> | ||||
<title>The JavaScript Object Notation (JSON) Data Interchange Format | ||||
</title> | ||||
<author fullname="T. Bray" initials="T." role="editor" surname="Bray | ||||
"/> | ||||
<date month="December" year="2017"/> | ||||
<abstract> | ||||
<t>JavaScript Object Notation (JSON) is a lightweight, text-based, | ||||
language-independent data interchange format. It was derived from the ECMAScrip | ||||
t Programming Language Standard. JSON defines a small set of formatting rules fo | ||||
r the portable representation of structured data.</t> | ||||
<t>This document removes inconsistencies with other specifications | ||||
of JSON, repairs specification errors, and offers experience-based interoperabi | ||||
lity guidance.</t> | ||||
</abstract> | ||||
</front> | ||||
<seriesInfo name="STD" value="90"/> | ||||
<seriesInfo name="RFC" value="8259"/> | ||||
<seriesInfo name="DOI" value="10.17487/RFC8259"/> | ||||
</reference> | ||||
<reference anchor="RFC7493"> | ||||
<front> | ||||
<title>The I-JSON Message Format</title> | ||||
<author fullname="T. Bray" initials="T." role="editor" surname="Bray | ||||
"/> | ||||
<date month="March" year="2015"/> | ||||
<abstract> | ||||
<t>I-JSON (short for "Internet JSON") is a restricted profile of J | ||||
SON designed to maximize interoperability and increase confidence that software | ||||
can process it successfully with predictable results.</t> | ||||
</abstract> | ||||
</front> | ||||
<seriesInfo name="RFC" value="7493"/> | ||||
<seriesInfo name="DOI" value="10.17487/RFC7493"/> | ||||
</reference> | ||||
<reference anchor="RFC6838"> | ||||
<front> | ||||
<title>Media Type Specifications and Registration Procedures</title> | ||||
<author fullname="N. Freed" initials="N." surname="Freed"/> | ||||
<author fullname="J. Klensin" initials="J." surname="Klensin"/> | ||||
<author fullname="T. Hansen" initials="T." surname="Hansen"/> | ||||
<date month="January" year="2013"/> | ||||
<abstract> | ||||
<t>This document defines procedures for the specification and regi | ||||
stration of media types for use in HTTP, MIME, and other Internet protocols. Thi | ||||
s memo documents an Internet Best Current Practice.</t> | ||||
</abstract> | ||||
</front> | ||||
<seriesInfo name="BCP" value="13"/> | ||||
<seriesInfo name="RFC" value="6838"/> | ||||
<seriesInfo name="DOI" value="10.17487/RFC6838"/> | ||||
</reference> | ||||
<reference anchor="I-D.draft-ietf-jsonpath-iregexp"> | ||||
<front> | ||||
<title>I-Regexp: An Interoperable Regexp Format</title> | ||||
<author fullname="Carsten Bormann" initials="C." surname="Bormann"> | ||||
<organization>Universität Bremen TZI</organization> | ||||
</author> | ||||
<author fullname="Tim Bray" initials="T." surname="Bray"> | ||||
<organization>Textuality</organization> | ||||
</author> | ||||
<date day="29" month="June" year="2023"/> | ||||
<abstract> | ||||
<t> This document specifies I-Regexp, a flavor of regular expres | ||||
sions | ||||
that is limited in scope with the goal of interoperation across many | ||||
different regular-expression libraries. | ||||
</t> | <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.0020.xml" | |||
</abstract> | /> | |||
</front> | <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8126.xm | |||
<seriesInfo name="Internet-Draft" value="draft-ietf-jsonpath-iregexp-0 | l"/> | |||
8"/> | <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.3629.xml" | |||
</reference> | /> | |||
<reference anchor="UNICODE" target="https://www.unicode.org/versions/Uni | <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.5234.xml" | |||
code14.0.0/UnicodeStandard-14.0.pdf"> | /> | |||
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8259.xml" | ||||
/> | ||||
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.7493.xml" | ||||
/> | ||||
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.6838.xml" | ||||
/> | ||||
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9485.xml" | ||||
/> | ||||
<reference anchor="UNICODE" target="https://www.unicode.org/versions/lat | ||||
est/"> | ||||
<front> | <front> | |||
<title>The Unicode® Standard: Version 14.0 - Core Specification</tit le> | <title>The Unicode® Standard</title> | |||
<author> | <author> | |||
<organization>The Unicode Consortium</organization> | <organization>The Unicode Consortium</organization> | |||
</author> | </author> | |||
<date year="2021" month="September"/> | ||||
</front> | </front> | |||
<annotation>At the time of writing, <eref target="https://www.unicode.o rg/versions/Unicode15.0.0/UnicodeStandard-15.0.pdf" brackets="angle"/>.</annotat ion> | ||||
</reference> | </reference> | |||
<reference anchor="RFC2119"> | ||||
<front> | <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml" | |||
<title>Key words for use in RFCs to Indicate Requirement Levels</tit | /> | |||
le> | <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml" | |||
<author fullname="S. Bradner" initials="S." surname="Bradner"/> | /> | |||
<date month="March" year="1997"/> | ||||
<abstract> | ||||
<t>In many standards track documents several words are used to sig | ||||
nify the requirements in the specification. These words are often capitalized. T | ||||
his document defines these words as they should be interpreted in IETF documents | ||||
. This document specifies an Internet Best Current Practices for the Internet Co | ||||
mmunity, and requests discussion and suggestions for improvements.</t> | ||||
</abstract> | ||||
</front> | ||||
<seriesInfo name="BCP" value="14"/> | ||||
<seriesInfo name="RFC" value="2119"/> | ||||
<seriesInfo name="DOI" value="10.17487/RFC2119"/> | ||||
</reference> | ||||
<reference anchor="RFC8174"> | ||||
<front> | ||||
<title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</ti | ||||
tle> | ||||
<author fullname="B. Leiba" initials="B." surname="Leiba"/> | ||||
<date month="May" year="2017"/> | ||||
<abstract> | ||||
<t>RFC 2119 specifies common key words that may be used in protoco | ||||
l specifications. This document aims to reduce the ambiguity by clarifying that | ||||
only UPPERCASE usage of the key words have the defined special meanings.</t> | ||||
</abstract> | ||||
</front> | ||||
<seriesInfo name="BCP" value="14"/> | ||||
<seriesInfo name="RFC" value="8174"/> | ||||
<seriesInfo name="DOI" value="10.17487/RFC8174"/> | ||||
</reference> | ||||
</references> | </references> | |||
<references anchor="sec-informative-references"> | <references anchor="sec-informative-references"> | |||
<name>Informative References</name> | <name>Informative References</name> | |||
<reference anchor="COMPARISON" target="https://cburgmer.github.io/json-p ath-comparison/"> | <reference anchor="COMPARISON" target="https://cburgmer.github.io/json-p ath-comparison/"> | |||
<front> | <front> | |||
<title>JSONPath Comparison</title> | <title>JSONPath Comparison</title> | |||
<author initials="C." surname="Burgmer" fullname="Christoph Burgmer" > | <author initials="C." surname="Burgmer" fullname="Christoph Burgmer" > | |||
<organization>Thoughtworks</organization> | <organization>Thoughtworks</organization> | |||
</author> | </author> | |||
<date>n.d.</date> | ||||
</front> | </front> | |||
</reference> | </reference> | |||
<reference anchor="RFC6901"> | ||||
<front> | <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.6901.xml" | |||
<title>JavaScript Object Notation (JSON) Pointer</title> | /> | |||
<author fullname="P. Bryan" initials="P." role="editor" surname="Bry | ||||
an"/> | ||||
<author fullname="K. Zyp" initials="K." surname="Zyp"/> | ||||
<author fullname="M. Nottingham" initials="M." role="editor" surname | ||||
="Nottingham"/> | ||||
<date month="April" year="2013"/> | ||||
<abstract> | ||||
<t>JSON Pointer defines a string syntax for identifying a specific | ||||
value within a JavaScript Object Notation (JSON) document.</t> | ||||
</abstract> | ||||
</front> | ||||
<seriesInfo name="RFC" value="6901"/> | ||||
<seriesInfo name="DOI" value="10.17487/RFC6901"/> | ||||
</reference> | ||||
<reference anchor="JSONPath-orig" target="https://goessner.net/articles/ JsonPath/"> | <reference anchor="JSONPath-orig" target="https://goessner.net/articles/ JsonPath/"> | |||
<front> | <front> | |||
<title>JSONPath — XPath for JSON</title> | <title>JSONPath - XPath for JSON</title> | |||
<author initials="S." surname="Gössner" fullname="Stefan Gössner"> | <author initials="S." surname="Gössner" fullname="Stefan Gössner"> | |||
<organization>Fachhochschule Dortmund</organization> | <organization>Fachhochschule Dortmund</organization> | |||
</author> | </author> | |||
<date year="2007" month="February" day="21"/> | <date year="2007" month="February"/> | |||
</front> | </front> | |||
</reference> | </reference> | |||
<reference anchor="XPath" target="https://www.w3.org/TR/2010/REC-xpath20 -20101214/"> | <reference anchor="XPath" target="https://www.w3.org/TR/2010/REC-xpath20 -20101214/"> | |||
<front> | <front> | |||
<title>XML Path Language (XPath) 2.0 (Second Edition)</title> | <title>XML Path Language (XPath) 2.0 (Second Edition)</title> | |||
<author fullname="Anders Berglund" role="editor"/> | <author fullname="Anders Berglund" role="editor"/> | |||
<author fullname="Don Chamberlin" role="editor"/> | <author fullname="Don Chamberlin" role="editor"/> | |||
<author fullname="Jerome Simeon" role="editor"/> | <author fullname="Jerome Simeon" role="editor"/> | |||
<author fullname="Jonathan Robie" role="editor"/> | <author fullname="Jonathan Robie" role="editor"/> | |||
<author fullname="Mary Fernandez" role="editor"/> | <author fullname="Mary Fernandez" role="editor"/> | |||
<author fullname="Michael Kay" role="editor"/> | <author fullname="Michael Kay" role="editor"/> | |||
<author fullname="Scott Boag" role="editor"/> | <author fullname="Scott Boag" role="editor"/> | |||
<date day="14" month="December" year="2010"/> | <date day="14" month="December" year="2010"/> | |||
</front> | </front> | |||
<seriesInfo name="W3C REC" value="REC-xpath20-20101214"/> | <seriesInfo name="W3C" value="REC-xpath20-20101214"/> | |||
<seriesInfo name="W3C" value="REC-xpath20-20101214"/> | ||||
</reference> | </reference> | |||
<reference anchor="E4X"> | ||||
<reference anchor="E4X" target="https://www.iso.org/standard/41002.html" | ||||
> | ||||
<front> | <front> | |||
<title>Information technology — ECMAScript for XML (E4X) specificati on</title> | <title>Information technology - ECMAScript for XML (E4X) specificati on</title> | |||
<author> | <author> | |||
<organization>ISO</organization> | <organization>ISO</organization> | |||
</author> | </author> | |||
<date year="2006"/> | <date year="2006" month="February"/> | |||
</front> | </front> | |||
<seriesInfo name="ISO/IEC 22537:2006" value=""/> | <seriesInfo name="ISO/IEC" value="22537:2006"/> | |||
<refcontent>Withdrawn</refcontent> | ||||
<annotation>An equivalent specification, also withdrawn, is available f | ||||
rom <eref target="https://ecma-international.org/publications-and-standards/stan | ||||
dards/ecma-357" brackets="angle"/>.</annotation> | ||||
</reference> | </reference> | |||
<reference anchor="SLICE" target="https://github.com/tc39/proposal-slice -notation"> | <reference anchor="SLICE" target="https://github.com/tc39/proposal-slice -notation"> | |||
<front> | <front> | |||
<title>Slice notation</title> | <title>Slice notation</title> | |||
<author> | <author> | |||
<organization/> | <organization/> | |||
</author> | </author> | |||
<date>n.d.</date> | <date month="July" year="2022"/> | |||
</front> | </front> | |||
<refcontent>commit 82f95b4</refcontent> | ||||
</reference> | </reference> | |||
<reference anchor="ECMA-262" target="https://www.ecma-international.org/ wp-content/uploads/ECMA-262_3rd_edition_december_1999.pdf"> | <reference anchor="ECMA-262" target="https://www.ecma-international.org/ wp-content/uploads/ECMA-262_3rd_edition_december_1999.pdf"> | |||
<front> | <front> | |||
<title>ECMAScript Language Specification, Standard ECMA-262, Third E dition</title> | <title>ECMAScript Language Specification</title> | |||
<author> | <author> | |||
<organization>Ecma International</organization> | <organization>ECMA International</organization> | |||
</author> | </author> | |||
<date year="1999" month="December"/> | <date year="1999" month="December"/> | |||
</front> | </front> | |||
<refcontent>Standard ECMA-262, Third Edition</refcontent> | ||||
</reference> | </reference> | |||
<reference anchor="RFC8949"> | ||||
<front> | <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8949.xml" | |||
<title>Concise Binary Object Representation (CBOR)</title> | /> | |||
<author fullname="C. Bormann" initials="C." surname="Bormann"/> | ||||
<author fullname="P. Hoffman" initials="P." surname="Hoffman"/> | <reference anchor="BOOLEAN-LAWS" target="https://en.wikipedia.org/w/inde | |||
<date month="December" year="2020"/> | x.php?title=Boolean_algebra&oldid=1191386550#Laws"> | |||
<abstract> | ||||
<t>The Concise Binary Object Representation (CBOR) is a data forma | ||||
t whose design goals include the possibility of extremely small code size, fairl | ||||
y small message size, and extensibility without the need for version negotiation | ||||
. These design goals make it different from earlier binary serializations such a | ||||
s ASN.1 and MessagePack.</t> | ||||
<t>This document obsoletes RFC 7049, providing editorial improveme | ||||
nts, new details, and errata fixes while keeping full compatibility with the int | ||||
erchange format of RFC 7049. It does not create a new version of the format.</t> | ||||
</abstract> | ||||
</front> | ||||
<seriesInfo name="STD" value="94"/> | ||||
<seriesInfo name="RFC" value="8949"/> | ||||
<seriesInfo name="DOI" value="10.17487/RFC8949"/> | ||||
</reference> | ||||
<reference anchor="BOOLEAN-LAWS" target="https://en.wikipedia.org/wiki/B | ||||
oolean_algebra#Laws"> | ||||
<front> | <front> | |||
<title>Boolean algebra laws</title> | <title>Boolean algebra: Laws</title> | |||
<author> | <author> | |||
<organization/> | <organization/> | |||
</author> | </author> | |||
<date>n.d.</date> | <date month="December" year="2023"/> | |||
</front> | </front> | |||
</reference> | </reference> | |||
</references> | </references> | |||
</references> | </references> | |||
<?line 2296?> | ||||
<section anchor="collected-abnf-grammars"> | <section anchor="collected-abnf-grammars"> | |||
<name>Collected ABNF grammars</name> | <name>Collected ABNF Grammars</name> | |||
<t>This appendix collects the ABNF grammar from the ABNF passages used | <t>This appendix collects the ABNF grammar from the ABNF passages used | |||
throughout the document.</t> | throughout the document.</t> | |||
<!-- Update the collected grammar files using `make sourcecode`, which --> | ||||
<!-- is currently manual as it creates a little circular dependency. --> | ||||
<!-- The filenames of the ::includes are likely to change when --> | ||||
<!-- kramdown-rfc-extract-sourcecode handles filenames better. --> | ||||
<t><xref target="jsonpath-abnf"/> contains the collected ABNF grammar that defin es the | <t><xref target="jsonpath-abnf"/> contains the collected ABNF grammar that defin es the | |||
syntax of a JSONPath query.</t> | syntax of a JSONPath query.</t> | |||
<figure anchor="jsonpath-abnf"> | <figure anchor="jsonpath-abnf"> | |||
<name>Collected ABNF of JSONPath queries</name> | <name>Collected ABNF of JSONPath Queries</name> | |||
<sourcecode type="abnf"><![CDATA[ | <sourcecode type="abnf"><![CDATA[ | |||
jsonpath-query = root-identifier segments | jsonpath-query = root-identifier segments | |||
segments = *(S segment) | segments = *(S segment) | |||
B = %x20 / ; Space | B = %x20 / ; Space | |||
%x09 / ; Horizontal tab | %x09 / ; Horizontal tab | |||
%x0A / ; Line feed or New line | %x0A / ; Line feed or New line | |||
%x0D ; Carriage return | %x0D ; Carriage return | |||
S = *B ; optional blank space | S = *B ; optional blank space | |||
root-identifier = "$" | root-identifier = "$" | |||
selector = name-selector / | selector = name-selector / | |||
wildcard-selector / | wildcard-selector / | |||
slice-selector / | slice-selector / | |||
index-selector / | index-selector / | |||
filter-selector | filter-selector | |||
name-selector = string-literal | name-selector = string-literal | |||
string-literal = %x22 *double-quoted %x22 / ; "string" | string-literal = %x22 *double-quoted %x22 / ; "string" | |||
%x27 *single-quoted %x27 ; 'string' | %x27 *single-quoted %x27 ; 'string' | |||
double-quoted = unescaped / | double-quoted = unescaped / | |||
%x27 / ; ' | %x27 / ; ' | |||
ESC %x22 / ; \" | ESC %x22 / ; \" | |||
ESC escapable | ESC escapable | |||
single-quoted = unescaped / | single-quoted = unescaped / | |||
%x22 / ; " | %x22 / ; " | |||
ESC %x27 / ; \' | ESC %x27 / ; \' | |||
ESC escapable | ESC escapable | |||
ESC = %x5C ; \ backslash | ESC = %x5C ; \ backslash | |||
unescaped = %x20-21 / ; see RFC 8259 | unescaped = %x20-21 / ; see RFC 8259 | |||
; omit 0x22 " | ; omit 0x22 " | |||
%x23-26 / | %x23-26 / | |||
; omit 0x27 ' | ; omit 0x27 ' | |||
%x28-5B / | %x28-5B / | |||
; omit 0x5C \ | ; omit 0x5C \ | |||
%x5D-D7FF / ; skip surrogate code points | %x5D-D7FF / | |||
; skip surrogate code points | ||||
%xE000-10FFFF | %xE000-10FFFF | |||
escapable = %x62 / ; b BS backspace U+0008 | escapable = %x62 / ; b BS backspace U+0008 | |||
%x66 / ; f FF form feed U+000C | %x66 / ; f FF form feed U+000C | |||
%x6E / ; n LF line feed U+000A | %x6E / ; n LF line feed U+000A | |||
%x72 / ; r CR carriage return U+000D | %x72 / ; r CR carriage return U+000D | |||
%x74 / ; t HT horizontal tab U+0009 | %x74 / ; t HT horizontal tab U+0009 | |||
"/" / ; / slash (solidus) U+002F | "/" / ; / slash (solidus) U+002F | |||
"\" / ; \ backslash (reverse solidus) U+005C | "\" / ; \ backslash (reverse solidus) U+005C | |||
(%x75 hexchar) ; uXXXX U+XXXX | (%x75 hexchar) ; uXXXX U+XXXX | |||
hexchar = non-surrogate / | hexchar = non-surrogate / | |||
(high-surrogate "\" %x75 low-surrogate) | (high-surrogate "\" %x75 low-surrogate) | |||
non-surrogate = ((DIGIT / "A"/"B"/"C" / "E"/"F") 3HEXDIG) / | non-surrogate = ((DIGIT / "A"/"B"/"C" / "E"/"F") 3HEXDIG) / | |||
("D" %x30-37 2HEXDIG ) | ("D" %x30-37 2HEXDIG ) | |||
high-surrogate = "D" ("8"/"9"/"A"/"B") 2HEXDIG | high-surrogate = "D" ("8"/"9"/"A"/"B") 2HEXDIG | |||
low-surrogate = "D" ("C"/"D"/"E"/"F") 2HEXDIG | low-surrogate = "D" ("C"/"D"/"E"/"F") 2HEXDIG | |||
HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F" | HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F" | |||
wildcard-selector = "*" | wildcard-selector = "*" | |||
index-selector = int ; decimal integer | index-selector = int ; decimal integer | |||
int = "0" / | int = "0" / | |||
(["-"] DIGIT1 *DIGIT) ; - optional | (["-"] DIGIT1 *DIGIT) ; - optional | |||
DIGIT1 = %x31-39 ; 1-9 non-zero digit | DIGIT1 = %x31-39 ; 1-9 non-zero digit | |||
skipping to change at line 3546 ¶ | skipping to change at line 3367 ¶ | |||
; binds more tightly than disjunction | ; binds more tightly than disjunction | |||
basic-expr = paren-expr / | basic-expr = paren-expr / | |||
comparison-expr / | comparison-expr / | |||
test-expr | test-expr | |||
paren-expr = [logical-not-op S] "(" S logical-expr S ")" | paren-expr = [logical-not-op S] "(" S logical-expr S ")" | |||
; parenthesized expression | ; parenthesized expression | |||
logical-not-op = "!" ; logical NOT operator | logical-not-op = "!" ; logical NOT operator | |||
test-expr = [logical-not-op S] | test-expr = [logical-not-op S] | |||
(filter-query / ; existence/non-existence | (filter-query / ; existence/non-existence | |||
function-expr) ; LogicalType or NodesType | function-expr) ; LogicalType or NodesType | |||
filter-query = rel-query / jsonpath-query | filter-query = rel-query / jsonpath-query | |||
rel-query = current-node-identifier segments | rel-query = current-node-identifier segments | |||
current-node-identifier = "@" | current-node-identifier = "@" | |||
comparison-expr = comparable S comparison-op S comparable | comparison-expr = comparable S comparison-op S comparable | |||
literal = number / string-literal / | literal = number / string-literal / | |||
true / false / null | true / false / null | |||
comparable = literal / | comparable = literal / | |||
singular-query / ; singular query value | singular-query / ; singular query value | |||
function-expr ; ValueType | function-expr ; ValueType | |||
comparison-op = "==" / "!=" / | comparison-op = "==" / "!=" / | |||
skipping to change at line 3596 ¶ | skipping to change at line 3417 ¶ | |||
child-segment = bracketed-selection / | child-segment = bracketed-selection / | |||
("." | ("." | |||
(wildcard-selector / | (wildcard-selector / | |||
member-name-shorthand)) | member-name-shorthand)) | |||
bracketed-selection = "[" S selector *(S "," S selector) S "]" | bracketed-selection = "[" S selector *(S "," S selector) S "]" | |||
member-name-shorthand = name-first *name-char | member-name-shorthand = name-first *name-char | |||
name-first = ALPHA / | name-first = ALPHA / | |||
"_" / | "_" / | |||
%x80-D7FF / ; skip surrogate code points | %x80-D7FF / | |||
; skip surrogate code points | ||||
%xE000-10FFFF | %xE000-10FFFF | |||
name-char = DIGIT / name-first | name-char = name-first / DIGIT | |||
DIGIT = %x30-39 ; 0-9 | DIGIT = %x30-39 ; 0-9 | |||
ALPHA = %x41-5A / %x61-7A ; A-Z / a-z | ALPHA = %x41-5A / %x61-7A ; A-Z / a-z | |||
descendant-segment = ".." (bracketed-selection / | descendant-segment = ".." (bracketed-selection / | |||
wildcard-selector / | wildcard-selector / | |||
member-name-shorthand) | member-name-shorthand) | |||
]]></sourcecode> | ]]></sourcecode> | |||
</figure> | </figure> | |||
<t><xref target="normalized-path-abnf"/> contains the collected ABNF gramm ar that | <t><xref target="normalized-path-abnf"/> contains the collected ABNF gramm ar that | |||
defines the syntax of a JSONPath Normalized Path, while also using the rules | defines the syntax of a JSONPath Normalized Path while also using the rules | |||
<tt>root-identifier</tt>, <tt>ESC</tt>, <tt>DIGIT</tt>, and <tt>DIGIT1</tt> from <xref target="jsonpath-abnf"/>.</t> | <tt>root-identifier</tt>, <tt>ESC</tt>, <tt>DIGIT</tt>, and <tt>DIGIT1</tt> from <xref target="jsonpath-abnf"/>.</t> | |||
<figure anchor="normalized-path-abnf"> | <figure anchor="normalized-path-abnf"> | |||
<name>Collected ABNF of JSONPath Normalized Paths</name> | <name>Collected ABNF of JSONPath Normalized Paths</name> | |||
<sourcecode type="abnf"><![CDATA[ | <sourcecode type="abnf"><![CDATA[ | |||
normalized-path = root-identifier *(normal-index-segment) | normalized-path = root-identifier *(normal-index-segment) | |||
normal-index-segment = "[" normal-selector "]" | normal-index-segment = "[" normal-selector "]" | |||
normal-selector = normal-name-selector / normal-index-selector | normal-selector = normal-name-selector / normal-index-selector | |||
normal-name-selector = %x27 *normal-single-quoted %x27 ; 'string' | normal-name-selector = %x27 *normal-single-quoted %x27 ; 'string' | |||
normal-single-quoted = normal-unescaped / | normal-single-quoted = normal-unescaped / | |||
ESC normal-escapable | ESC normal-escapable | |||
normal-unescaped = ; omit %x0-1F control codes | normal-unescaped = ; omit %x0-1F control codes | |||
%x20-26 / | %x20-26 / | |||
; omit 0x27 ' | ; omit 0x27 ' | |||
%x28-5B / | %x28-5B / | |||
; omit 0x5C \ | ; omit 0x5C \ | |||
%x5D-D7FF / ; skip surrogate code points | %x5D-D7FF / | |||
; skip surrogate code points | ||||
%xE000-10FFFF | %xE000-10FFFF | |||
normal-escapable = %x62 / ; b BS backspace U+0008 | normal-escapable = %x62 / ; b BS backspace U+0008 | |||
%x66 / ; f FF form feed U+000C | %x66 / ; f FF form feed U+000C | |||
%x6E / ; n LF line feed U+000A | %x6E / ; n LF line feed U+000A | |||
%x72 / ; r CR carriage return U+000D | %x72 / ; r CR carriage return U+000D | |||
%x74 / ; t HT horizontal tab U+0009 | %x74 / ; t HT horizontal tab U+0009 | |||
"'" / ; ' apostrophe U+0027 | "'" / ; ' apostrophe U+0027 | |||
"\" / ; \ backslash (reverse solidus) U+005C | "\" / ; \ backslash (reverse solidus) U+005C | |||
(%x75 normal-hexchar) | (%x75 normal-hexchar) | |||
; certain values u00xx U+00XX | ; certain values u00xx U+00XX | |||
normal-hexchar = "0" "0" | normal-hexchar = "0" "0" | |||
( | ( | |||
("0" %x30-37) / ; "00"-"07" | ("0" %x30-37) / ; "00"-"07" | |||
; omit U+0008-U+000A BS HT LF | ; omit U+0008-U+000A BS HT LF | |||
("0" %x62) / ; "0b" | ("0" %x62) / ; "0b" | |||
; omit U+000C-U+000D FF CR | ; omit U+000C-U+000D FF CR | |||
("0" %x65-66) / ; "0e"-"0f" | ("0" %x65-66) / ; "0e"-"0f" | |||
("1" normal-HEXDIG) | ("1" normal-HEXDIG) | |||
) | ) | |||
normal-HEXDIG = DIGIT / %x61-66 ; "0"-"9", "a"-"f" | normal-HEXDIG = DIGIT / %x61-66 ; "0"-"9", "a"-"f" | |||
normal-index-selector = "0" / (DIGIT1 *DIGIT) | normal-index-selector = "0" / (DIGIT1 *DIGIT) | |||
; non-negative decimal integer | ; non-negative decimal integer | |||
]]></sourcecode> | ]]></sourcecode> | |||
</figure> | </figure> | |||
</section> | </section> | |||
<section anchor="inspired-by-xpath"> | <section anchor="inspired-by-xpath"> | |||
<name>Inspired by XPath</name> | <name>Inspired by XPath</name> | |||
<t>This appendix is informative.</t> | <t>This appendix is informative.</t> | |||
<t>At the time JSONPath was invented, XML was noted for the availability o f | <t>At the time JSONPath was invented, XML was noted for the availability o f | |||
powerful tools to analyze, transform and selectively extract data from | powerful tools to analyze, transform, and selectively extract data from | |||
XML documents. | XML documents. | |||
<xref target="XPath"/> is one of these tools.</t> | <xref target="XPath"/> is one of these tools.</t> | |||
<t>In 2007, the need for something solving the same class of problems for | <t>In 2007, the need for something solving the same class of problems for | |||
the emerging JSON community became apparent, specifically for:</t> | the emerging JSON community became apparent, specifically for:</t> | |||
<ul spacing="normal"> | <ul spacing="normal"> | |||
<li>Finding data interactively and extracting them out of <xref target=" | <li>finding data interactively and extracting them out of | |||
RFC8259"/> | JSON values <xref target="RFC8259"/> without special scripting and</li> | |||
JSON values without special scripting.</li> | <li>specifying the relevant parts of the JSON data in a request by a | |||
<li>Specifying the relevant parts of the JSON data in a request by a | ||||
client, so the server can reduce the amount of data in its response, | client, so the server can reduce the amount of data in its response, | |||
minimizing bandwidth usage.</li> | minimizing bandwidth usage.</li> | |||
</ul> | </ul> | |||
<t>(Note: XPath has evolved since 2007, and recent versions even | <t>(Note: XPath has evolved since 2007, and recent versions even | |||
nominally support operating inside JSON values. | nominally support operating inside JSON values. | |||
This appendix only discusses the more widely used version of XPath | This appendix only discusses the more widely used version of XPath | |||
that was available in 2007.)</t> | that was available in 2007.)</t> | |||
<t>JSONPath picks up the overall feeling of XPath, but maps the concepts | <t>JSONPath picks up the overall feeling of XPath but maps the concepts | |||
to syntax (and partially semantics) that would be familiar to someone | to syntax (and partially semantics) that would be familiar to someone | |||
using JSON in a dynamic language.</t> | using JSON in a dynamic language.</t> | |||
<t>E.g., in popular dynamic programming languages such as JavaScript, | <t>For example, in popular dynamic programming languages such as JavaScrip | |||
Python and PHP, the semantics of the XPath expression</t> | t, | |||
Python, and PHP, the semantics of the XPath expression:</t> | ||||
<sourcecode type="xpath"><![CDATA[ | <sourcecode type="xpath"><![CDATA[ | |||
/store/book[1]/title | /store/book[1]/title | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t>can be realized in the expression</t> | <t>can be realized in the expression:</t> | |||
<sourcecode type="xpath"><![CDATA[ | <sourcecode type="xpath"><![CDATA[ | |||
x.store.book[0].title | x.store.book[0].title | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t>or, in bracket notation,</t> | <t>or in bracket notation:</t> | |||
<sourcecode type="xpath"><![CDATA[ | <sourcecode type="xpath"><![CDATA[ | |||
x['store']['book'][0]['title'] | x['store']['book'][0]['title'] | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t>with the variable x holding the query argument.</t> | <t>with the variable x holding the query argument.</t> | |||
<t>The JSONPath language was designed to:</t> | <t>The JSONPath language was designed to:</t> | |||
<ul spacing="normal"> | <ul spacing="normal"> | |||
<li>be naturally based on those language characteristics;</li> | <li>be naturally based on those language characteristics,</li> | |||
<li>cover only the most essential parts of XPath 1.0;</li> | <li>cover only the most essential parts of XPath 1.0,</li> | |||
<li>be lightweight in code size and memory consumption;</li> | <li>be lightweight in code size and memory consumption, and</li> | |||
<li>be runtime efficient.</li> | <li>be runtime efficient.</li> | |||
</ul> | </ul> | |||
<section anchor="xpath-overview"> | <section anchor="xpath-overview"> | |||
<name>JSONPath and XPath</name> | <name>JSONPath and XPath</name> | |||
<t>JSONPath expressions apply to JSON values in the same way | <t>JSONPath expressions apply to JSON values in the same way | |||
as XPath expressions are used in combination with an XML document. | as XPath expressions are used in combination with an XML document. | |||
JSONPath uses <tt>$</tt> to refer to the root node of the query argument, simila r | JSONPath uses <tt>$</tt> to refer to the root node of the query argument, simila r | |||
to XPath's <tt>/</tt> at the front.</t> | to XPath's <tt>/</tt> at the front.</t> | |||
<t>JSONPath expressions move further down the hierarchy using <em>dot no tation</em> | <t>JSONPath expressions move further down the hierarchy using <em>dot notation</ em> | |||
(<tt>$.store.book[0].title</tt>) | (<tt>$.store.book[0].title</tt>) | |||
or the <em>bracket notation</em> | or the <em>bracket notation</em> | |||
(<tt>$['store']['book'][0]['title']</tt>), a lightweight/limited, and a more | (<tt>$['store']['book'][0]['title']</tt>); both replace XPath's <tt>/</tt> withi | |||
heavyweight syntax replacing XPath's <tt>/</tt> within query expressions.</t> | n query expressions, where <em>dot notation</em> serves as a lightweight but lim | |||
ited syntax while <em>bracket notation</em> is a | ||||
heavyweight but more general syntax.</t> | ||||
<t>Both JSONPath and XPath use <tt>*</tt> for a wildcard. | <t>Both JSONPath and XPath use <tt>*</tt> for a wildcard. | |||
The descendant operators, starting with <tt>..</tt>, borrowed from <xref target= "E4X"/>, are similar to XPath's <tt>//</tt>. | JSONPath's descendant segment notation, starting with <tt>..</tt>, borrowed from <xref target="E4X"/>, is similar to XPath's <tt>//</tt>. | |||
The array slicing construct <tt>[start:end:step]</tt> is unique to JSONPath, | The array slicing construct <tt>[start:end:step]</tt> is unique to JSONPath, | |||
inspired by <xref target="SLICE"/> from ECMASCRIPT 4.</t> | inspired by <xref target="SLICE"/> from ECMASCRIPT 4.</t> | |||
<t>Filter expressions are supported via the syntax <tt>?<logical-expr | <t>Filter expressions are supported via the syntax <tt>?<logical-expr | |||
></tt> as in</t> | ></tt> as in:</t> | |||
<sourcecode type="JSONPath"><![CDATA[ | <sourcecode type="application/jsonpath"><![CDATA[ | |||
$.store.book[?@.price < 10].title | $.store.book[?@.price < 10].title | |||
]]></sourcecode> | ]]></sourcecode> | |||
<t><xref target="tbl-xpath-overview"/> extends <xref target="tbl-overvie w"/> by providing a comparison | <t><xref target="tbl-xpath-overview"/> extends <xref target="tbl-overvie w"/> by providing a comparison | |||
with similar XPath concepts.</t> | with similar XPath concepts.</t> | |||
<table anchor="tbl-xpath-overview"> | <table anchor="tbl-xpath-overview"> | |||
<name>XPath syntax compared to JSONPath</name> | <name>XPath Syntax Compared to JSONPath</name> | |||
<thead> | <thead> | |||
<tr> | <tr> | |||
<th align="left">XPath</th> | <th align="left">XPath</th> | |||
<th align="left">JSONPath</th> | <th align="left">JSONPath</th> | |||
<th align="left">Description</th> | <th align="left">Description</th> | |||
</tr> | </tr> | |||
</thead> | </thead> | |||
<tbody> | <tbody> | |||
<tr> | <tr> | |||
<td align="left"> | <td align="left"> | |||
skipping to change at line 3757 ¶ | skipping to change at line 3580 ¶ | |||
<tr> | <tr> | |||
<td align="left"> | <td align="left"> | |||
<tt>..</tt></td> | <tt>..</tt></td> | |||
<td align="left">n/a</td> | <td align="left">n/a</td> | |||
<td align="left">parent operator</td> | <td align="left">parent operator</td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="left"> | <td align="left"> | |||
<tt>//</tt></td> | <tt>//</tt></td> | |||
<td align="left"> | <td align="left"> | |||
<tt>..name</tt>, <tt>..[index]</tt>, <tt>..*</tt>, or <tt>..[*]< /tt></td> | <tt>..name</tt>, <tt>..&wj;[index]</tt>, <tt>..*</tt>, or <tt>.. [*]</tt></td> | |||
<td align="left">descendants (JSONPath borrows this syntax from E4 X)</td> | <td align="left">descendants (JSONPath borrows this syntax from E4 X)</td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="left"> | <td align="left"> | |||
<tt>*</tt></td> | <tt>*</tt></td> | |||
<td align="left"> | <td align="left"> | |||
<tt>*</tt></td> | <tt>*</tt></td> | |||
<td align="left">wildcard: All XML elements regardless of their na mes</td> | <td align="left">wildcard: All XML elements regardless of their na mes</td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
skipping to change at line 3813 ¶ | skipping to change at line 3636 ¶ | |||
<td align="left">expression engine</td> | <td align="left">expression engine</td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="left"> | <td align="left"> | |||
<tt>()</tt></td> | <tt>()</tt></td> | |||
<td align="left">n/a</td> | <td align="left">n/a</td> | |||
<td align="left">grouping</td> | <td align="left">grouping</td> | |||
</tr> | </tr> | |||
</tbody> | </tbody> | |||
</table> | </table> | |||
<!-- Note: the weirdness about the vertical bar above is intentional --> | ||||
<t>For further illustration, <xref target="tbl-xpath-equivalents"/> shows some X Path expressions | <t>For further illustration, <xref target="tbl-xpath-equivalents"/> shows some X Path expressions | |||
and their JSONPath equivalents.</t> | and their JSONPath equivalents.</t> | |||
<table anchor="tbl-xpath-equivalents"> | <table anchor="tbl-xpath-equivalents"> | |||
<name>Example XPath expressions and their JSONPath equivalents</name> | <name>Example XPath Expressions and Their JSONPath Equivalents</name> | |||
<thead> | <thead> | |||
<tr> | <tr> | |||
<th align="left">XPath</th> | <th align="left">XPath</th> | |||
<th align="left">JSONPath</th> | <th align="left">JSONPath</th> | |||
<th align="left">Result</th> | <th align="left">Result</th> | |||
</tr> | </tr> | |||
</thead> | </thead> | |||
<tbody> | <tbody> | |||
<tr> | <tr> | |||
<td align="left"> | <td align="left"> | |||
skipping to change at line 3871 ¶ | skipping to change at line 3692 ¶ | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="left"> | <td align="left"> | |||
<tt>//book[last()]</tt></td> | <tt>//book[last()]</tt></td> | |||
<td align="left"> | <td align="left"> | |||
<tt>$..book[-1]</tt></td> | <tt>$..book[-1]</tt></td> | |||
<td align="left">the last book in order</td> | <td align="left">the last book in order</td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="left"> | <td align="left"> | |||
<tt>//book[position()<3]</tt></td> | <tt>//&wj;book[position()<3]</tt></td> | |||
<td align="left"> | <td align="left"> | |||
<tt>$..book[0,1]</tt><br/><tt>$..book[:2]</tt></td> | <tt>$..book[0,1]</tt><br/><tt>$..book[:2]</tt></td> | |||
<td align="left">the first two books</td> | <td align="left">the first two books</td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="left"> | <td align="left"> | |||
<tt>//book[isbn]</tt></td> | <tt>//book[isbn]</tt></td> | |||
<td align="left"> | <td align="left"> | |||
<tt>$..book[?@.isbn]</tt></td> | <tt>$..book[?@.isbn]</tt></td> | |||
<td align="left">filter all books with isbn number</td> | <td align="left">filter all books with an ISBN number</td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="left"> | <td align="left"> | |||
<tt>//book[price<10]</tt></td> | <tt>//book[price<10]</tt></td> | |||
<td align="left"> | <td align="left"> | |||
<tt>$..book[?@.price<10]</tt></td> | <tt>$..book[?@.price<10]</tt></td> | |||
<td align="left">filter all books cheaper than 10</td> | <td align="left">filter all books cheaper than 10</td> | |||
</tr> | </tr> | |||
<tr> | <tr> | |||
<td align="left"> | <td align="left"> | |||
<tt>//*</tt></td> | <tt>//*</tt></td> | |||
<td align="left"> | <td align="left"> | |||
<tt>$..*</tt></td> | <tt>$..*</tt></td> | |||
<td align="left">all elements in XML document; all member values a nd array elements contained in input value</td> | <td align="left">all elements in an XML document; all member value s and array elements contained in input value</td> | |||
</tr> | </tr> | |||
</tbody> | </tbody> | |||
</table> | </table> | |||
<t>XPath has a lot more functionality (location paths in unabbreviated s yntax, | <t>XPath has a lot more functionality (location paths in unabbreviated s yntax, | |||
operators and functions) than listed in this comparison. Moreover, there are | operators, and functions) than listed in this comparison. Moreover, there are | |||
significant differences in how the subscript operator works in XPath and | significant differences in how the subscript operator works in XPath and | |||
JSONPath:</t> | JSONPath:</t> | |||
<ul spacing="normal"> | <ul spacing="normal"> | |||
<li>Square brackets in XPath expressions always operate on the <em>nod e | <li>Square brackets in XPath expressions always operate on the <em>nod e | |||
set</em> resulting from the previous path fragment. Indices always start | set</em> resulting from the previous path fragment. Indices always start | |||
at 1.</li> | at 1.</li> | |||
<li>With JSONPath, square brackets operate on each of the nodes in the <em>nodelist</em> | <li>With JSONPath, square brackets operate on each of the nodes in the <em>nodelist</em> | |||
resulting from the previous query segment. Array indices always start | resulting from the previous query segment. Array indices always start | |||
at 0.</li> | at 0.</li> | |||
</ul> | </ul> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="json-pointer"> | <section anchor="json-pointer"> | |||
<name>JSON Pointer</name> | <name>JSON Pointer</name> | |||
<t>This appendix is informative.</t> | <t>This appendix is informative.</t> | |||
<t>JSONPath is not intended as a replacement for, but as a more powerful | <t>In relation to JSON Pointer <xref target="RFC6901"/>, JSONPath is not i | |||
companion to, JSON Pointer <xref target="RFC6901"/>. The purposes of the two sta | ntended as a replacement but as a more powerful | |||
ndards | companion. The purposes of the two standards | |||
are different.</t> | are different.</t> | |||
<t>JSON Pointer is for identifying a single value within a JSON value whos e | <t>JSON Pointer is for identifying a single value within a JSON value whos e | |||
structure is known.</t> | structure is known.</t> | |||
<t>JSONPath can identify a single value within a JSON value, for example b y | <t>JSONPath can identify a single value within a JSON value, for example, by | |||
using a Normalized Path. But JSONPath is also a query syntax that can be used | using a Normalized Path. But JSONPath is also a query syntax that can be used | |||
to search for and extract multiple values from JSON values whose structure | to search for and extract multiple values from JSON values whose structure | |||
is known only in a general way.</t> | is known only in a general way.</t> | |||
<t>A Normalized JSONPath can be converted into a JSON Pointer by convertin g the syntax, | <t>A Normalized JSONPath can be converted into a JSON Pointer by convertin g the syntax, | |||
without knowledge of any JSON value. The inverse is not generally true: a numeri c | without knowledge of any JSON value. The inverse is not generally true, i.e., a numeric | |||
reference token (path component) in a JSON Pointer may identify a member value o f an object or an element of an array. | reference token (path component) in a JSON Pointer may identify a member value o f an object or an element of an array. | |||
For conversion to a JSONPath query, knowledge of the structure of the JSON value is | For conversion to a JSONPath query, knowledge of the structure of the JSON value is | |||
needed to distinguish these cases.</t> | needed to distinguish these cases.</t> | |||
</section> | </section> | |||
<section numbered="false" anchor="acknowledgements"> | <section numbered="false" anchor="acknowledgements"> | |||
<name>Acknowledgements</name> | <name>Acknowledgements</name> | |||
<t>This document is based on <contact fullname="Stefan Gössner"/>'s | <t>This document is based on <contact fullname="Stefan Gössner"/>'s | |||
original online article defining JSONPath <xref target="JSONPath-orig"/>.</t> | original online article defining JSONPath <xref target="JSONPath-orig"/>.</t> | |||
<t>The books example was taken from | <t>The books example was taken from course material that Bielefeld University, G | |||
http://coli.lili.uni-bielefeld.de/~andreas/Seminare/sommer02/books.xml | ermany used in 2002.</t> | |||
— a dead link now.</t> | <t>This work is indebted to <contact fullname="Christoph Burgmer"/> for th | |||
<t>This work is indebted to Christoph Burgmer for the superb | e superb | |||
JSONPath comparison project <xref target="COMPARISON"/> detailing the behavior o | JSONPath comparison project <xref target="COMPARISON"/> that details the behavio | |||
f over forty JSONPath | r of over forty JSONPath | |||
implementations applied to numerous queries.</t> | implementations applied to numerous queries.</t> | |||
<!-- LocalWords: JSONPath XPath nodelist memoization | ||||
--> | ||||
</section> | </section> | |||
<section anchor="contributors" numbered="false" toc="include" removeInRFC="f alse"> | <section anchor="contributors" numbered="false" toc="include"> | |||
<name>Contributors</name> | <name>Contributors</name> | |||
<contact initials="M." surname="Mikulicic" fullname="Marko Mikulicic"> | <contact initials="M." surname="Mikulicic" fullname="Marko Mikulicic"> | |||
<organization>InfluxData, Inc.</organization> | <organization>InfluxData, Inc.</organization> | |||
<address> | <address> | |||
<postal> | <postal> | |||
<city>Pisa</city> | <city>Pisa</city> | |||
<country>IT</country> | <country>Italy</country> | |||
</postal> | </postal> | |||
<email>mmikulicic@gmail.com</email> | <email>mmikulicic@gmail.com</email> | |||
</address> | </address> | |||
</contact> | </contact> | |||
<contact initials="E." surname="Surov" fullname="Edward Surov"> | <contact initials="E." surname="Surov" fullname="Edward Surov"> | |||
<organization>TheSoul Publishing Ltd.</organization> | <organization>TheSoul Publishing Ltd.</organization> | |||
<address> | <address> | |||
<postal> | <postal> | |||
<city>Limassol</city> | <city>Limassol</city> | |||
<country>Cyprus</country> | <country>Cyprus</country> | |||
skipping to change at line 3980 ¶ | skipping to change at line 3796 ¶ | |||
<postal> | <postal> | |||
<city>Auckland</city> | <city>Auckland</city> | |||
<country>New Zealand</country> | <country>New Zealand</country> | |||
</postal> | </postal> | |||
<email>gregsdennis@yahoo.com</email> | <email>gregsdennis@yahoo.com</email> | |||
<uri>https://github.com/gregsdennis</uri> | <uri>https://github.com/gregsdennis</uri> | |||
</address> | </address> | |||
</contact> | </contact> | |||
</section> | </section> | |||
</back> | </back> | |||
<!-- ##markdown-source: | ||||
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 | ||||
AA== | ||||
</rfc> | </rfc> | |||
End of changes. 311 change blocks. | ||||
1506 lines changed or deleted | 562 lines changed or added | |||
This html diff was produced by rfcdiff 1.48. |