JSON 10 ๐ JSON Path for Querying and Extracting Nested Data
JSONPath is a query language for JSON, and it is to JSON what XPath is to XML. It defines a string syntax for selecting and extracting values from within a JSON document, and the query returns a nodelistโzero or more nodes that match the expression . The language was designed to cover only the essential parts of XPath 1.0, to be lightweight in code size and memory consumption, and to be runtime efficient . The RFC 9535, published in February 2024, is the proposed standard that formalizes the syntax and the semantics, and it is the reference that the implementations are converging on .
The syntax borrows the familiar notation from the JavaScript property access. The $ is the root of the query argument, the dot notation ($.store.book) and the bracket notation ($['store']['book']) are the child operators, the .. is the recursive descent, and the * is the wildcard . The filter expression is the ?() syntax, and the @ is the current node being processed by the filter . The combination is the query language, and the query is the mechanism that extracts the nested data without writing the manual traversal code.
Key point: JSONPath uses $ for the root, @ for the current node, . or [] for the child access, .. for the recursive descent, and * for the wildcard. The filter expression ?() selects the nodes that satisfy the logical condition, and the @ inside the filter refers to the current node. The RFC 9535 is the standard, and the implementations vary in the supported extensions.
Why JSONPath exists
The nested access problem. A JSON document is a tree, and the manual traversal of the tree requires the nested loops and the null checks. The JSONPath is the declarative expression that describes the path, and the engine does the traversal. The $.store.book[0].title is the path to the first book’s title, and the path is the mechanism that replaces the manual data.store.book[0].title access with the query .
The filtering problem. The data extraction often needs the conditionโthe books cheaper than 10, the users with the active status, the orders with the pending state. The filter expression ?(@.price < 10) is the mechanism that selects the nodes that satisfy the condition, and the filter is the query-language feature that the manual traversal cannot express without the explicit loop .
The recursive problem. The data structure is not always known in advance, and the same key can appear at the different depths. The recursive descent $..author is the mechanism that finds every author key at any depth, and the recursion is the feature that the fixed path cannot express .
The portability problem. The JSONPath is the language, not the library. The same expression works in the JavaScript, the Python, the Java, and the Go implementations, and the portability is the reason the query is the cross-language mechanism . The RFC 9535 is the standardization that makes the portability reliable.
The trade-off. The JSONPath is the query language, and the implementations vary in the extensions. The RFC 9535 defines the core, and the implementations add the functions, the operators, and the syntax that the standard does not cover. The standardization is the core, and the extensions are the variation.
a. The syntax and the operators
The JSONPath expression starts with the $, and the $ is the root of the query argument. The dot notation is the child access, and the bracket notation is the alternative that supports the special characters and the multiple selections.
// The dot notation
$.store.book[0].title
// The bracket notation
$['store']['book'][0]['title']
The .. is the recursive descent. It searches the current node and all its descendants for the matching name, and the $..author returns every author value at any depth .
// The recursive descent
$..author
// The result is every author in the document.
The * is the wildcard. It matches every child of the current node, and the $.store.* returns the books and the bicycle, which are the children of the store .
// The wildcard
$.store.*
// The result is the books array and the bicycle object.
The array index and the slice are the array access. The [0] is the first element, the [-1] is the last element, and the [0:2] is the slice from the index 0 to the index 2 (exclusive) .
// The array index
$..book[2] // The third book
$..book[-1] // The last book
// The array slice
$..book[0:2] // The first two books
The filter expression is the ?() syntax. The expression inside the parentheses is the logical condition, and the @ is the current node being processed .
// The filter expression
$..book[?(@.price < 10)]
// The result is the books cheaper than 10.
The filter supports the comparison operators (==, !=, <, <=, >, >=), the logical operators (&&, ||), and the existence test (?(@.isbn)). The string literals are enclosed in the single or the double quotes, and the regex match is the implementation-specific extension .
// The existence test
$..book[?(@.isbn)] // The books with an ISBN
// The logical combination
$..book[?(@.price < 10 && @.category == 'fiction')]
b. The RFC 9535 and the implementation variations
The RFC 9535 is the proposed standard that defines the JSONPath syntax and the semantics. It specifies the selectorsโthe name selector, the index selector, the slice selector, the wildcard selector, and the filter selectorโand the function extensions . The standard is the core, and the implementations are converging on it.
// The RFC 9535 example queries
$.store.book[*].author // The authors of all books
$..author // All authors
$.store.* // All things in the store
$.store..price // The prices of everything in the store
$..book[2] // The third book
$..book[-1] // The last book
$..book[0,1] // The first two books
$..book[:2] // The first two books
$..book[?(@.isbn)] // The books with an ISBN
$..book[?(@.price<10)] // The books cheaper than 10
$..* // All member values and array elements
The implementation variations are the functions, the operators, and the syntax that the standard does not cover. The json_path_plus Dart package supports the @parent, the @root, the @path, the @property operators, the type operators (@string(), @number()), the ~ property-name operator, and the ^ parent selector . The Oracle implementation supports the min(), the max(), the avg(), the stddev(), and the length() functions . The IBM implementation supports the regex match with the =~ operator and the &&/|| logical combination .
// The implementation-specific extensions
$..book[?(@.price > 10)].title // The filter with the property access
$..book[?(@.price > $.expensive)] // The comparison with the root value
The JavaScript implementations are the jsonpath-plus, the jsonpath, and the json-p3 packages. The jsonpath-plus is the most feature-complete, and it supports the @parent, the @root, the @path, the @property, and the type operators. The json-p3 is the RFC 9535 compliant implementation . The Python implementation is the python-jsonpath-rfc9535, and it is the RFC 9535 compliant implementation .
Complete Example Session
// ============================================
// PART 1: THE SAMPLE DATA
// ============================================
const 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 }
}
};
// ============================================
// PART 2: THE DOT NOTATION
// ============================================
const titles = JSONPath.query("$.store.book[*].title", data);
// ["Sayings of the Century", "Sword of Honour", "Moby Dick", "The Lord of the Rings"]
// ============================================
// PART 3: THE BRACKET NOTATION
// ============================================
const firstTitle = JSONPath.query("$['store']['book'][0]['title']", data);
// ["Sayings of the Century"]
// ============================================
// PART 4: THE RECURSIVE DESCENT
// ============================================
const authors = JSONPath.query("$..author", data);
// ["Nigel Rees", "Evelyn Waugh", "Herman Melville", "J. R. R. Tolkien"]
// ============================================
// PART 5: THE WILDCARD
// ============================================
const storeItems = JSONPath.query("$.store.*", data);
// [the books array, the bicycle object]
// ============================================
// PART 6: THE ARRAY INDEX AND SLICE
// ============================================
const thirdBook = JSONPath.query("$..book[2]", data);
const lastBook = JSONPath.query("$..book[-1]", data);
const firstTwo = JSONPath.query("$..book[0:2]", data);
// ============================================
// PART 7: THE FILTER EXPRESSION
// ============================================
const cheapBooks = JSONPath.query("$..book[?(@.price < 10)]", data);
// The books cheaper than 10.
// ============================================
// PART 8: THE EXISTENCE TEST
// ============================================
const booksWithIsbn = JSONPath.query("$..book[?(@.isbn)]", data);
// The books with an ISBN.
// ============================================
// PART 9: THE LOGICAL COMBINATION
// ============================================
const cheapFiction = JSONPath.query(
"$..book[?(@.price < 10 && @.category == 'fiction')]",
data
);
// The fiction books cheaper than 10.
// ============================================
// PART 10: THE CHECKLIST
// ============================================
// [ ] The $ is the root.
// [ ] The @ is the current node.
// [ ] The . or [] is the child access.
// [ ] The .. is the recursive descent.
// [ ] The * is the wildcard.
// [ ] The ?() is the filter expression.
// [ ] The RFC 9535 is the standard.
The ten parts covered the sample data, the dot notation, the bracket notation, the recursive descent, the wildcard, the array index and slice, the filter expression, the existence test, the logical combination, and the checklist. The through-line is that the JSONPath is the declarative query, and the operators are the traversal and the selection.
Quick Reference
The core operators
| Operator | Meaning | Example |
|---|---|---|
$ | The root | $ |
@ | The current node | @.price |
. or [] | The child access | $.store |
.. | The recursive descent | $..author |
* | The wildcard | $.store.* |
[n] | The array index | $..book[2] |
[start:end] | The array slice | $..book[0:2] |
?() | The filter | $..book[?(@.price<10)] |
The filter operators
| Operator | Meaning |
|---|---|
== | The equal |
!= | The not equal |
< | The less than |
<= | The less or equal |
> | The greater than |
>= | The greater or equal |
&& | The logical AND |
|| | The logical OR |
The RFC 9535 example queries
| Query | Result |
|---|---|
$.store.book[*].author | The authors of all books |
$..author | All authors |
$.store.* | All things in the store |
$.store..price | The prices of everything |
$..book[2] | The third book |
$..book[-1] | The last book |
$..book[0,1] | The first two books |
$..book[?(@.isbn)] | The books with an ISBN |
$..book[?(@.price<10)] | The books cheaper than 10 |
$..* | All member values |
The implementations
| Language | Package | Notes |
|---|---|---|
| JavaScript | jsonpath-plus | The feature-complete |
| JavaScript | json-p3 | The RFC 9535 compliant |
| Python | python-jsonpath-rfc9535 | The RFC 9535 compliant |
| Dart | json_path_plus | The RFC 9535 filters |
| Go | github.com/pb33f/jsonpath | The Go implementation |
Best Practices
โ Do This:
// Use the recursive descent for the unknown depth
$..author // โ
// Use the filter for the conditional selection
$..book[?(@.price < 10)] // โ
// Use the slice for the array range
$..book[0:2] // โ
โ Don’t Do This:
// Use the fixed path when the depth is unknown
$.store.book[0].author // only the first book // โ
// Use the manual loop for the filtering
// The filter expression is the declarative alternative. // โ
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
| The result is empty | The path does not match | Check the path against the data |
| The filter does not match | The @ is missing | Use @.price inside the filter |
| The recursive descent is slow | The full tree is traversed | Use the narrower path |
| The implementation differs | The extensions are not standard | Use the RFC 9535 core |
Real-World Examples
1. The root
$ // The whole document
2. The child access
$.store.book
3. The recursive descent
$..author
4. The wildcard
$.store.*
5. The array index
$..book[2]
6. The array slice
$..book[0:2]
7. The filter
$..book[?(@.price < 10)]
8. The existence test
$..book[?(@.isbn)]
9. The logical combination
$..book[?(@.price < 10 && @.category == 'fiction')]
10. The implementation
JSONPath.query("$..author", data)
Visual
The Path Structure
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ THE JSONPATH STRUCTURE โ
โ โ
โ $ โ
โ โ The root โ
โ โผ โ
โ .store โ
โ โ The child access โ
โ โผ โ
โ .book โ
โ โ The child access โ
โ โผ โ
โ [*] โ
โ โ The wildcard โ
โ โผ โ
โ .author โ
โ The child access โ
โ โ
โ The query selects the authors of all the books. โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
The Recursive Descent
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ THE RECURSIVE DESCENT โ
โ โ
โ $..author โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ The engine searches โ Every node at any depth โ
โ โ the whole tree โ for the "author" key โ
โ โโโโโโโโโโโโฌโโโโโโโโโโโ โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ The result is the โ The nodelist of the matching โ
โ โ authors โ nodes โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
The Filter Expression
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ THE FILTER โ
โ โ
โ $..book[?(@.price < 10)] โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ The filter is the โ The @ is the current node โ
โ โ logical condition โ (the book) โ
โ โโโโโโโโโโโโฌโโโโโโโโโโโ โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ The result is the โ The books that satisfy the โ
โ โ matching nodes โ condition โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Summary
| Item | Value |
|---|---|
| The root | $ |
| The current node | @ |
| The child access | . or [] |
| The recursive descent | .. |
| The wildcard | * |
| The filter | ?() |
| The standard | RFC 9535 |
| The array index | [n] |
| The array slice | [start:end] |
Key takeaways:
- JSONPath is the query language for JSON, and it is to JSON what XPath is to XML. The
$is the root, the@is the current node, the.or the[]is the child access, the..is the recursive descent, and the*is the wildcard . - The filter expression
?()is the conditional selection. The@inside the filter refers to the current node, and the comparison operators, the logical operators, and the existence test are the condition . - The RFC 9535 is the proposed standard. It defines the selectors and the function extensions, and the implementations are converging on it . The implementation variations are the extensions that the standard does not cover.
- The recursive descent is the unknown-depth mechanism. The
$..authorfinds everyauthorat any depth, and the recursion is the feature that the fixed path cannot express . - The implementations vary in the extensions. The
jsonpath-plusis the feature-complete JavaScript implementation, and thejson-p3is the RFC 9535 compliant one . The choice is the standard compliance against the extensions.
Remember: JSONPath is the declarative query for the JSON. The $ is the root, the @ is the current node, the . is the child access, the .. is the recursive descent, and the * is the wildcard. The filter expression ?() is the conditional selection, and the RFC 9535 is the standard. The query is the mechanism that extracts the nested data without the manual traversal.
Stop using slow, ad-bloated tool sites! ๐คฎ
๐ Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
โ
Finance (Mortgage, Interest, Inflation)
โ
Tech (Base64, JSON, Dev Suite, IP)
โ
Health (BMI, BMR, TDEE)
โ
Productivity (Timer, Workspace, QR)
โก๏ธ Fast & Private
๐ No data leaves your device
๐ 100% Free
๐ Use it now: https://tools.kandz.me
๐ Bookmark itโyouโll need it later!