JSONPath Query Guide: Extracting Data Like a Pro
JSONPath is a query language for JSON, similar to how XPath works for XML. When you are dealing with complex, deeply nested JSON responses from APIs, JSONPath lets you extract exactly the data you need without writing loops and conditionals. This guide covers the syntax, operators, and real-world patterns you need.
Why JSONPath?
Consider a typical API response with nested data:
{
"store": {
"books": [
{ "title": "Clean Code", "author": "Robert Martin", "price": 32.99, "tags": ["programming", "best-practices"] },
{ "title": "Design Patterns", "author": "Gang of Four", "price": 44.99, "tags": ["programming", "architecture"] },
{ "title": "The Pragmatic Programmer", "author": "Hunt & Thomas", "price": 39.99, "tags": ["programming", "career"] }
],
"music": [
{ "title": "Kind of Blue", "artist": "Miles Davis", "price": 12.99 }
]
}
}
To get all book titles, you could write a loop β or use JSONPath: $.store.books[*].title
Basic Syntax
| Expression | Description |
|---|---|
$ | Root object |
. | Child operator |
.. | Recursive descent (search all levels) |
[*] | Wildcard (all elements) |
[n] | Array index (0-based) |
[n,m] | Multiple indices |
[start:end:step] | Array slice |
[?()] | Filter expression |
@ | Current element (in filters) |
Dot Notation vs Bracket Notation
Both notations access properties, but bracket notation is required for special characters:
# Dot notation
$.store.books[0].title
# Bracket notation (equivalent)
$['store']['books'][0]['title']
# Required for keys with special characters
$['store']['price-range']
Array Operations
Indexing
$.store.books[0] # First book
$.store.books[-1] # Last book
$.store.books[0,2] # First and third books
Slicing
$.store.books[0:2] # First two books (index 0 and 1)
$.store.books[1:] # All books except the first
$.store.books[:2] # First two books
$.store.books[::2] # Every other book
Wildcards
$.store.books[*].title # All book titles
$.store.* # All store collections (books, music)
$..title # All titles at any depth
$..price # All prices at any depth
The recursive descent operator (..) is particularly powerful for extracting values regardless of their position in the hierarchy.
Filter Expressions
Filters select elements based on conditions:
# Books cheaper than $40
$.store.books[?(@.price < 40)]
# Books by a specific author
$.store.books[?(@.author == 'Robert Martin')]
# Books with more than 2 tags
$.store.books[?(@.tags.length > 2)]
# Books that have a 'price' property
$.store.books[?(@.price)]
Combining Filters
# Books under $40 by programming tag
$.store.books[?(@.price < 40 && @.tags[0] == 'programming')]
Real-World Examples
Extracting from API Responses
GitHub API β get all repository names:
$[*].name
Weather API β get today's temperature:
$.daily[0].temp.day
E-commerce API β get all product images:
$.products[*].images[0].url
Configuration Extraction
Docker Compose β get all service names:
$.services.*~
Package.json β get all dependency names:
$.dependencies.*~
JSONPath vs jq
JSONPath and jq are both JSON query tools, but they serve different contexts:
| Feature | JSONPath | jq |
|---|---|---|
| Environment | Libraries, APIs | Command line |
| Syntax | XPath-inspired | Custom functional |
| Transformation | Query only | Query + transform |
| Standard | RFC 9535 | De facto standard |
For command-line JSON processing, jq is more powerful. For embedding queries in applications or using in web tools, JSONPath is more widely supported.
Try JSONPath expressions interactively with our JSON Path Explorer. Paste your JSON, write a query, and see results instantly.
Implementation Examples
JavaScript (jsonpath-plus)
const { JSONPath } = require('jsonpath-plus');
const result = JSONPath({
path: '$.store.books[?(@.price < 40)].title',
json: data
});
// ["Clean Code", "The Pragmatic Programmer"]
Python (jsonpath-ng)
from jsonpath_ng import parse
expr = parse('$.store.books[*].title')
titles = [match.value for match in expr.find(data)]
RFC 9535: The JSONPath Standard
In February 2024, JSONPath was officially standardized as RFC 9535. This addresses historical inconsistencies between implementations. Key standardized behaviors:
- Array indices are 0-based
- Filter expressions use
@for the current element - String comparison is case-sensitive
- The result is always an array of matched values
If you are choosing a JSONPath library, prefer one that supports RFC 9535 for consistent behavior.
FAQ
What is the difference between JSONPath and JSON Pointer?
JSONPath is a query language that can match multiple values using wildcards and filters. JSON Pointer (RFC 6901) is a simple path syntax that addresses exactly one value: /store/books/0/title. Use JSONPath when you need to search or filter; use JSON Pointer when you know the exact path.
Can JSONPath modify JSON data?
Standard JSONPath is read-only β it extracts but does not modify data. Some libraries extend JSONPath with set/delete operations, but these are non-standard. For transformations, consider jq (command line) or write application code. For viewing and exploring JSON structure, our JSON Formatter helps you understand the data before writing queries.
Related Resources
- JSON Path Explorer β Test JSONPath expressions in your browser
- JSON Formatting Best Practices β Structure your JSON for easier querying
- JSON Schema Validation Guide β Validate the structure your JSONPath queries expect