-
-
Notifications
You must be signed in to change notification settings - Fork 23
YAML Path versus JSONPath
Self-described as "XPath for JSON", the JSONPath specification dictates a particular dialect for selecting data nodes from JSON-encapsulated data. It also offers implementations of its specification in both JavaScript and PHP.
There are several topics to discuss when contrasting YAML Path with JSONPath, including:
- the relationship between JSON and YAML;
- contrast JSONPath and YAML Path syntax;
- demonstrate addressing capabilities of both; and
- discuss their reference implementations.
YAML is a superset of JSON. This means that YAML processors -- like YAML Path -- are wholly compatible with JSON data; they are fully capable of reading and writing JSON and YAML. Being a superset, this also means that YAML offers more capabilities than JSON alone.
While JSONPath compares itself most closely to XPath when discussing its syntax, it does not employ the familiar /
(forward-slash) segment separator from XPath. Rather, JSONPath offers two different separator styles: a .
(dot) separator or "bracket notation" where each segment is individually demarcated via a []
(square-bracket) pair. Like XPath's forward-slash, when using the dot separator, the JSONPath dot separator is expected before the first segment. Unlike XPath, JSONPath also mandates a prefix of $
to indicate the path root, like $.segment1.segment2.segmentN
or $['segment1']['segment2']['segmentN']
.
YAML Path also offers two different separator styles: .
(dot) or /
(forward-slash). With regard to the forward-slash, YAML Path more closely matches XPath than JSONPath does. There is no need for a $
prefix with YAML Path. When using dot-notation, a YAML Path needn't start with a dot, but doing so anyway is harmless (a leading dot is ignored).
Separator | XPath | JSONPath | YAML Path |
---|---|---|---|
/ |
/segment1/segment2/segmentN |
N/A | /segment1/segment2/segmentN |
. |
Address the present node | $.segment1.segment2.segmentN |
segment1.segment2.segmentN |
[] |
Demarcate Expressions | $['segment1']['segment2']['segmentN'] |
Demarcate Expressions |
YAML Path is more comprehensive in its addressing capabilities than is JSONPath, owing primarily to the additional capabilities of YAML. Neither YAML Path nor JSONPath are as comprehensive as XPath is. For a side-by-side contrast in JSONPath's own terms, the following table is copied -- and expanded -- from the same table found at the JSONPath site:
XPath | JSONPath | YAML Path | Description |
---|---|---|---|
/ |
$ |
/ when using forward-slash notation, nothing for dot notation |
The root object/element |
. |
@ |
. |
The current object/element |
/ |
. or []
|
/ or .
|
Child operator |
.. |
N/A | [parent([STEPS])] |
Parent operator |
max() , min()
|
N/A |
[max(NAME)] , [min(NAME)] (Search Keywords) |
Aggregate functions |
name() |
N/A |
[name()] (Search Keywords) |
Name of the present node; YAML Path also uses this to reveal the index of the present element |
*[NAME] |
N/A | [has_child(NAME)] |
Select nodes having a NAMEd child |
// |
.. |
** |
Recursive descent |
* |
* |
* |
Wildcard |
@ |
N/A | N/A | Attribute access; neither JSON nor YAML have attributes |
[] |
[] |
[] |
Subscript operator |
() |
N/A |
() (Collectors) |
Grouping |
| |
[,] |
()+() (Collector Math) |
Union operator |
except |
N/A |
()-() (Collector Math) |
Difference (subtraction) operator |
intersect |
N/A |
()&() (Collector Math) |
Intersection operator |
N/A | [start:end:step] |
[start:end] |
Array slice operator |
[] |
?() |
[] (Search Expressions) |
Filter (script) expression |
N/A | () |
N/A | Script expression, using the underlying script engine |
N/A | N/A | & |
Anchor/Alias/YAML Merge Key name matching |
> , < , >= , <= , = , !=
|
> , < , >= , <=
|
> , < , >= , <= , = , != (Search Expressions) |
Comparison operators |
matches() |
N/A | =~ |
Regular Expression matches |
YAML Path also provides other robust node selection capabilities like Pass-Through Selections for Arrays of Hashes, Hash Slices, and other Search Expression operators.
For a side-by-side comparison of JSONPath and YAML Path, consider the following examples from the JSONPath documentation with YAML Paths added.
Sample Data:
{ "store": {
"book": [
{ "category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{ "category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{ "category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{ "category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
}
}
XPath | JSONPath | YAML Path | Result |
---|---|---|---|
/store/book/author |
$.store.book[*].author |
/store/book/author |
the authors of all books in the store |
//author |
$..author |
/**/author |
all authors |
/store/* |
$.store.* |
/store/* |
all things in store, which are some books and a red bicycle |
/store//price |
$.store..price |
/store/**/price |
the price of everything in the store |
//book[3] |
$..book[2] |
/**/book[2] |
the third book |
//book[last()] |
$..book[(@.length-1)] , $..book[-1:]
|
/**/book[-1] |
the last book in order |
//book[position()<3] |
$..book[0,1] , $..book[:2]
|
/**/book[0:2] |
the first two books |
//book[isbn] |
$..book[?(@.isbn)] |
/**/book[.=isbn] |
filter all books with ISBN Number |
//book[price<10] |
$..book[?(@.price<10)] |
/**/book[price<10] |
filter all books cheaper than 10 |
//* |
$..* |
/** |
every node in the data |
It should be noted that both of the JavaScript and PHP reference implementations of JSONPath internally use the eval
function to execute arbitrary code passed along as a segment of a JSONPath. The reference implementation for YAML Path does not. There is ample public domain information discouraging the use of eval
, especially when evaluating user-supplied code.
In addition, the JSONPath project seems to be dead. It's last release was in February 2008, despite its author listing some ideas for future work on its primary website.