JSONPath: Difference between revisions

From NovaOrdis Knowledge Base
Jump to navigation Jump to search
 
(96 intermediate revisions by the same user not shown)
Line 12: Line 12:
JSONPath is a query language for JSON similar to [[XPath]] for [[XML]]. Some documentation describes it as a Java DSL for reading JSON documents, probably to address those cases where the implementation is made in Java.
JSONPath is a query language for JSON similar to [[XPath]] for [[XML]]. Some documentation describes it as a Java DSL for reading JSON documents, probably to address those cases where the implementation is made in Java.


=Concepts=
=JSONPath Expression=
==JSONPath Expression==
A JSONPath expression specifies a [[JSON_Concepts#Path|path]] to an [[JSON_Concepts#Element|element]] or a set of elements that are part of a [[JSON_Concepts#JSON_Document|JSON document]].
A JSONPath expression specifies a [[JSON_Concepts#Path|path]] to an [[JSON_Concepts#Element|element]] or a set of elements that are part of a [[JSON_Concepts#JSON_Document|JSON document]]. An expression can be assembled using the series of syntax elements presented below.  
<syntaxhighlight lang='json'>
.spec.containers[0].name
</syntaxhighlight>
The expressions, including fields and values, are case-sensitive. Unlike XPath, JSONPath does not have operations for accessing parent or sibling nodes from a given nodes. An expression can be assembled using a series of syntax elements presented below.  


There are two ways to select a specific child element relative to the parent element: .''property'' and []. These two different syntaxes are applied to JSON [[JSON_Concepts#Objects|Objects]] and [[JSON_Concepts#Arrays|Arrays]], given the fact that JSON has only these two types of collections.
==<tt>$</tt>==


====<tt>.''property''</tt>====
$ represents the [[JSON_Concepts#Top-Level_Element|top-level element]] (or root) of the JSON document. The "$" is optional, the following are equivalent:
====<tt>[''n'']</tt>====
<syntaxhighlight lang='json'>
$.metadata
.metadata
</syntaxhighlight>
Some JSONPath documentation mentions that even the leading dot can be omitted, but that may break some tools, as it is the case with [[Kubectl_get_JSONPath_Support#Overview|kubectl JSONPath support]].


==JSONPath Template==
==Element Selection==
 
There are two ways to select a specific child element relative to the parent element: the dot notation [[#.field|.''field'']] (or its variant [[#.5Bfield.5D|[&#39;''field'' &#39;]]]) and [[#Array_Element_Selection|index-based selection]]. These two different forms are applied to JSON [[JSON_Concepts#Objects|Objects]] and [[JSON_Concepts#Arrays|Arrays]], respectively, given the fact that JSON has only these two types of collections. Both forms are called the '''child operator'''.
 
===Object Fields Selection===
 
====<tt>.''field''</tt>====
This is called "the dot notation". The expression selects the specified [[JSON_Concepts#Field|field]] in the parent JSON [[JSON_Concepts#Objects|Object]].
<syntaxhighlight lang='json'>
.metadata.resourceVersion
</syntaxhighlight>
 
====<tt>[&#39;''field''&#39;]</tt>====
This is an equivalent variant of the dot notation that can used to select the specified field of a parent Object. It requires quotes around the field name and it is useful when the field name contains special characters such as spaces, or they begin with a character other than A..Za..z_.
<syntaxhighlight lang='json'>
['metadata']['resourceVersion']
</syntaxhighlight>
[[Kubectl_get_JSONPath_Support#Overview|kubectl JSONPath support]] supports this notation.
 
====<tt>..''field''</tt> (Field Recursive Descent)====
The expression searches for the specified field name recursively, starting with the specified path element, and returns a list of all values for this field name. It always returns a list if just one property is found. If not such field is found, the result is an empty list.
<syntaxhighlight lang='json'>
..name
</syntaxhighlight>
 
===Array Element Selection===
[[JSON_Concepts#Arrays|Array]] elements are selected using 0-based indexes. All these are called '''subscript operators'''.
 
====<tt>[''0-based-index'']</tt>====
The expression selects the element whose index is specified between square brackets from a JSON [[JSON_Concepts#Arrays|Array]].
 
====<tt>[''index1'', ''index2'', ...]</tt>====
The expression selects the elements with the specified indexes from a JSON Array and returns <font color=darkgray>a space-separated list</font>. If the element with the specified index does not exist, the result is tool-dependent. For example, [[Kubectl_get_JSONPath_Support#Overview|kubectl JSONPath support]] raises an error.
====<tt>[''start'':''end''], [''start'':]</tt>====
The expression selects the elements from the ''start'' index and up to, but not including, the ''end'' index. If ''end'' is omitted, it selects all elements from ''start'' until the end of the array. It returns <font color=darkgray>a space-separated list</font>. If the element with the specified index does not exist, the result is tool-dependent. For example, [[Kubectl_get_JSONPath_Support#Overview|kubectl JSONPath support]] raises an error.
 
Some implementation support:
<syntaxhighlight lang='text'>
[start:end:step]
</syntaxhighlight>
 
====<tt>[:''n'']</tt>====
The expression selects the first ''n'' elements of the array. It returns <font color=darkgray>a space-separated list</font>. If more elements than available are requested, the result is tool-dependent. For example, [[Kubectl_get_JSONPath_Support#Overview|kubectl JSONPath support]] raises an error.
====<tt>[-''n'':]</tt>====
The expression selects the last ''n'' elements of the array. It returns <font color=darkgray>a space-separated list</font>. If more elements than available are requested, the result is tool-dependent. For example, [[Kubectl_get_JSONPath_Support#Overview|kubectl JSONPath support]] raises an error.
====Array Length====
<syntaxhighlight lang='groovy'>
.array_name.length()
</syntaxhighlight>
<font color=darkkhaki>Did not work</font>
 
===* (Wildcard)===
Wildcard applies to both Object and Array elements and selects all fields/array elements, regardless of their names or indexes.
 
To apply it to an Object element:
<syntaxhighlight lang='bash'>
.metadata.*
</syntaxhighlight>
 
To apply it to an Array:
<syntaxhighlight lang='bash'>
.status.conditions[*]
</syntaxhighlight>
 
Note that dot notation can be applied to the result of the wildcard expression. If the expression is applied to an array, and there are more than one element in an array, a space separated list will be returned:
<syntaxhighlight lang='bash'>
.status.conditions[*].lastTransitionTime
</syntaxhighlight>
returns:
<syntaxhighlight lang='bash'>
2021-03-03T18:40:00Z 2021-03-05T17:29:23Z 2021-03-05T17:29:23Z 2021-03-03T18:40:00Z
</syntaxhighlight>
 
==<tt>@</tt>==
"@" is the JSONPath syntax element used in [[#Filter_Expressions|filter expressions]] and [[#Script_Expressions|script expressions]] to refer to the current node being processed.
==<span id='.5B.2C.5D'></span><tt>[,] (Union Operator)</tt>==
The union operator allows alternate names or array indices as a set.
<syntaxhighlight lang='bash'>
.items[*]['metadata.name', 'status.capacity']
</syntaxhighlight>
 
==Filter Expressions==
<syntaxhighlight lang='bash'>
?(expression)
</syntaxhighlight>
A filter expression is a logical expression used to filter Object fields or array elements.
 
To select elements of an Array, combine the filter expression with [...]:
<syntaxhighlight lang='bash'>
[?(expression)]
</syntaxhighlight>
 
<font color=darkgray>TODO: To select the fields of an Object, use it as such:
<syntaxhighlight lang='bash'>
.?(expression)]
</syntaxhighlight>
</font>
 
A filter expression selects all fields in an Object or all elements in an Array that match the specified filter. It returns a list.
 
[[#.40|@]] can be used in the filter expression to represent the current node being processed - in this case, the array element being evaluated:
<syntaxhighlight lang='bash'>
.status.conditions[?(@.status==False)]
</syntaxhighlight>
The components of the filter expressions are:
* identifiers (@.status is an identifier)
* [[JSONPath#Filter_Expression_Operators|operators]]
* operands (strings and numbers). Strings must be quoted. Quote requirements (single or double quotes) depend on the tool.
Filter expressions can use [[#.24|$]] to refer to elements outside the object being evaluated:
<syntaxhighlight lang='bash'>
.store.book[?(@.price < $.expensive)]
</syntaxhighlight>
 
An expression that specifies just a field name, such as <code>[?(@.isbn)]</code>, matches all elements that
have this field, regardless of the value.
 
===Multiple Filter Expression on the Same Path===
Multiple filter expressions can be applied to the same path.
<syntaxhighlight lang='bash'>
.items[*].spec.volumes[?(@.name=="config-volume")]
</syntaxhighlight>
will select to volume objects.
<syntaxhighlight lang='bash'>
.items[?(@.metadata.name=="coredns-f9fd979d6-c9pg4")].spec.volumes[?(@.name=="config-volume")]
</syntaxhighlight>
will select just one.
 
===Filter Expression Operators===
====<tt>==</tt>====
Equals to. String values must be quoted. The type of quote depends on the tool.
 
====<tt>!=</tt>====
Not Equal to. String values must be quoted. The type of quote depends on the tool.
 
====<tt>></tt>====
====<tt>>=</tt>====
====<tt><</tt>====
====<tt><=</tt>====
====<tt>!</tt>====
Negate a filter.
====<tt>&&</tt>====
Logical AND, used to combine multiple filter expressions:
<syntaxhighlight lang='bash'>
[?(@.category=='fiction' && @.price < 10)]
</syntaxhighlight>
 
⚠️ As per kubectl 1.19.7, "&&" is not supported in JSONPath expressions:
<syntaxhighlight lang='text'>
error: error parsing jsonpath {.items[?(@.spec.claimRef.name=="something" && @.spec.claimRef.namespace=="somethingelse")].metadata.name}, unrecognized character in action: U+0026 '&'
</syntaxhighlight>
 
====<tt>||</tt>====
Logical OR, used to combine multiple filter expressions:
<syntaxhighlight lang='bash'>
[?(@.category=='fiction' || @.price < 10)]
</syntaxhighlight>
 
==Script Expressions==
<syntaxhighlight lang='bash'>
[(expression)]
</syntaxhighlight>
A script expression can be used for both Objects and Arrays instead of explicit field names or indexes. [[#.40|@]] can be referred from expression to represent the current node being processed.

Latest revision as of 05:36, 4 May 2022

External

Internal

Overview

JSONPath is a query language for JSON similar to XPath for XML. Some documentation describes it as a Java DSL for reading JSON documents, probably to address those cases where the implementation is made in Java.

JSONPath Expression

A JSONPath expression specifies a path to an element or a set of elements that are part of a JSON document.

.spec.containers[0].name

The expressions, including fields and values, are case-sensitive. Unlike XPath, JSONPath does not have operations for accessing parent or sibling nodes from a given nodes. An expression can be assembled using a series of syntax elements presented below.

$

$ represents the top-level element (or root) of the JSON document. The "$" is optional, the following are equivalent:

$.metadata
.metadata

Some JSONPath documentation mentions that even the leading dot can be omitted, but that may break some tools, as it is the case with kubectl JSONPath support.

Element Selection

There are two ways to select a specific child element relative to the parent element: the dot notation .field (or its variant ['field ']) and index-based selection. These two different forms are applied to JSON Objects and Arrays, respectively, given the fact that JSON has only these two types of collections. Both forms are called the child operator.

Object Fields Selection

.field

This is called "the dot notation". The expression selects the specified field in the parent JSON Object.

.metadata.resourceVersion

['field']

This is an equivalent variant of the dot notation that can used to select the specified field of a parent Object. It requires quotes around the field name and it is useful when the field name contains special characters such as spaces, or they begin with a character other than A..Za..z_.

['metadata']['resourceVersion']

kubectl JSONPath support supports this notation.

..field (Field Recursive Descent)

The expression searches for the specified field name recursively, starting with the specified path element, and returns a list of all values for this field name. It always returns a list if just one property is found. If not such field is found, the result is an empty list.

..name

Array Element Selection

Array elements are selected using 0-based indexes. All these are called subscript operators.

[0-based-index]

The expression selects the element whose index is specified between square brackets from a JSON Array.

[index1, index2, ...]

The expression selects the elements with the specified indexes from a JSON Array and returns a space-separated list. If the element with the specified index does not exist, the result is tool-dependent. For example, kubectl JSONPath support raises an error.

[start:end], [start:]

The expression selects the elements from the start index and up to, but not including, the end index. If end is omitted, it selects all elements from start until the end of the array. It returns a space-separated list. If the element with the specified index does not exist, the result is tool-dependent. For example, kubectl JSONPath support raises an error.

Some implementation support:

[start:end:step]

[:n]

The expression selects the first n elements of the array. It returns a space-separated list. If more elements than available are requested, the result is tool-dependent. For example, kubectl JSONPath support raises an error.

[-n:]

The expression selects the last n elements of the array. It returns a space-separated list. If more elements than available are requested, the result is tool-dependent. For example, kubectl JSONPath support raises an error.

Array Length

.array_name.length()

Did not work

* (Wildcard)

Wildcard applies to both Object and Array elements and selects all fields/array elements, regardless of their names or indexes.

To apply it to an Object element:

.metadata.*

To apply it to an Array:

.status.conditions[*]

Note that dot notation can be applied to the result of the wildcard expression. If the expression is applied to an array, and there are more than one element in an array, a space separated list will be returned:

.status.conditions[*].lastTransitionTime

returns:

2021-03-03T18:40:00Z 2021-03-05T17:29:23Z 2021-03-05T17:29:23Z 2021-03-03T18:40:00Z

@

"@" is the JSONPath syntax element used in filter expressions and script expressions to refer to the current node being processed.

[,] (Union Operator)

The union operator allows alternate names or array indices as a set.

.items[*]['metadata.name', 'status.capacity']

Filter Expressions

?(expression)

A filter expression is a logical expression used to filter Object fields or array elements.

To select elements of an Array, combine the filter expression with [...]:

[?(expression)]

TODO: To select the fields of an Object, use it as such:

.?(expression)]

A filter expression selects all fields in an Object or all elements in an Array that match the specified filter. It returns a list.

@ can be used in the filter expression to represent the current node being processed - in this case, the array element being evaluated:

.status.conditions[?(@.status==False)]

The components of the filter expressions are:

  • identifiers (@.status is an identifier)
  • operators
  • operands (strings and numbers). Strings must be quoted. Quote requirements (single or double quotes) depend on the tool.

Filter expressions can use $ to refer to elements outside the object being evaluated:

.store.book[?(@.price < $.expensive)]

An expression that specifies just a field name, such as [?(@.isbn)], matches all elements that have this field, regardless of the value.

Multiple Filter Expression on the Same Path

Multiple filter expressions can be applied to the same path.

.items[*].spec.volumes[?(@.name=="config-volume")]

will select to volume objects.

.items[?(@.metadata.name=="coredns-f9fd979d6-c9pg4")].spec.volumes[?(@.name=="config-volume")]

will select just one.

Filter Expression Operators

==

Equals to. String values must be quoted. The type of quote depends on the tool.

!=

Not Equal to. String values must be quoted. The type of quote depends on the tool.

>

>=

<

<=

!

Negate a filter.

&&

Logical AND, used to combine multiple filter expressions:

[?(@.category=='fiction' && @.price < 10)]

⚠️ As per kubectl 1.19.7, "&&" is not supported in JSONPath expressions:

error: error parsing jsonpath {.items[?(@.spec.claimRef.name=="something" && @.spec.claimRef.namespace=="somethingelse")].metadata.name}, unrecognized character in action: U+0026 '&'

||

Logical OR, used to combine multiple filter expressions:

[?(@.category=='fiction' || @.price < 10)]

Script Expressions

[(expression)]

A script expression can be used for both Objects and Arrays instead of explicit field names or indexes. @ can be referred from expression to represent the current node being processed.