10. Extracting JSON Values with JsonPath
XPath is used to extract values from XML documents. JsonPath performs this task for JSON documents. Chapter introduces you to JsonPath.
Note
If youre unfamiliar with XPath, I recommend that you read Chapter before reading this chapter. JsonPath was derived from XPath.
What Is JsonPath?
JsonPath is a declarative query language (also known as a path-expression-syntax) for selecting and extracting a JSON documents property values . For example, you can use JsonPath to locate "John" in {"firstName": "John"} and return this value. JsonPath is based on XPath 1.0.
JsonPath was created by Stefan Goessner ( http://goessner.net ). Goessner also created JavaScript-based and PHP-based implementations of JsonPath. For complete documentation, check out Goessners website ( http://goessner.net/articles/JsonPath/index.html ).
Swedish software company Jayway ( www.jayway.com ) subsequently adapted JsonPath to Java. Their Java version of JsonPath is the focus of this chapter. You will find complete documentation on Jayways implementation of JsonPath at http://github.com/jayway/JsonPath .
Learning the JsonPath Language
JsonPath is a simple language with various features that are similar to their XPath counterparts . This language is used to construct path expressions.
A JsonPath expression begins with the dollar sign ( $ ) character, which refers to the root element of a query. The dollar sign is followed by a sequence of child elements, which are separated via dot ( . ) notation or via square bracket ( [] ) notation. For example, consider the following JSON object:
{
"firstName": "John",
"lastName": "Smith",
"age": 25,
"address":
{
"streetAddress": "21 2nd Street",
"city": "New York",
"state": "NY",
"postalCode": "10021-3100"
},
"phoneNumbers":
[
{
"type": "home",
"number": "212 555-1234"
},
{
"type": "office",
"number": "646 555-4567"
}
]
}
The following dot notation-based JsonPath expression extracts, from the previous anonymous JSON object, the phone number ( 212 555-1234 ) thats assigned to the number field in the anonymous JSON object, which is assigned to the first element in the phoneNumbers array:
$.phoneNumbers[0].number
The $ character represents the anonymous root JSON object. The leftmost dot character separates the object root from the phoneNumbers property name. The [0] syntax identifies the first element in the array assigned to phoneNumbers .
The first array element stores an anonymous object consisting of "type": "home" and "number": "212 555-1234" properties. The rightmost dot character accesses this objects number child property name, which is assigned the value 212 555-1234 . This value is returned from the expression.
Alternatively, I could specify the following square bracket notation to extract the same phone number:
$['phoneNumbers'][0]['number']
The Jayway documentation identifies $ as an operator and also identifies several other basic operators. Table describes these operators.
Table 10-1
JsonPath Basic Operators
Operator | Description |
---|
$ | The root element to query. This operator starts all path expressions. Its equivalent to XPaths / symbol. |
@ | The current node being processed by a filter predicate. Its equivalent to XPaths . symbol. |
* | Wildcard. Available anywhere a name or numeric value is required. |
.. | Deep scan (also known as recursive descent). Available anywhere a name is required. Its equivalent to XPaths // symbol. |
. name | Dot-notated child. The dot is equivalent to XPaths / symbol. |
[' name ' (, ' name ')] | Bracket-notated child or children. |
[ number (, number )] | Array index or indexes. |
[ start : end ] | Array slice operator. |
[?( expression )] | Filter operator. The expression must evaluate to a Boolean value. In other words, its a predicate. |
The Jayway documentation also identifies several functions that can be invoked at the tail end of a paththe input to a function is the output of the path expression; the function output is dictated by the function itself. Table describes these functions.
Table 10-2
JsonPath Functions
Function | Description |
---|
min() | Return the minimum value (as a double ) in an array of numbers. |
max() | Return the maximum value (as a double ) in an array of numbers. |
avg() | Return the average value (as a double ) of an array of numbers. |
stddev() | Return the standard deviation value (as a double ) of an array of numbers. |
length() | Return the length (as an int ) of an array. |
Finally, the Jayway documentation identifies various operators for
filters, which use predicates (Boolean expressions) to restrict returned lists of items . Predicates can use the filter operators in Table to determine equality, match regular expressions, and test for inclusion.
Table 10-3
JsonPath Filter Operators
Operator | Description |
---|
== | Return true when the left operand equals the right operand. Note that is not equal to '1' (i.e., number and string are two different things). |
!= | Return true when the left operand doesnt equal the right operand. |
< | Return true when the left operand is less than the right operand. |
<= | Return true when the left operand is less than or equal to the right operand. |
> | Return true when the left operand is greater than the right operand. |
>= | Return true when the left operand is greater than or equal to the right operand. |
=~ | Return true when the left operand matches the regular expression specified by the right operand; for example, [?(@.name =~ /foo.*?/i)] . |
in | Return true when the left operand exists in the right operand; for example, [?(@.grade in ['A', 'B'])] . |
nin | Return true when the left operand doesnt exist in the right operand. |
subsetof | Return true when the left operand (an array) is a subset of the right operand (an array); for example, [?(@.sizes subsetof ['S', 'M', 'L'])] . |
size | Return true when the size of the left operand (an array or string) matches the right operand (an integer). |
empty | Return true when the left operand (an array or string) is empty and the right operand is true , or return true when the left operand is not empty and the right operand is false . |