JSONPath is a query language for JSON, similar to how XPath works for XML. Instead of writing nested loops to dig out a value, you write a short path expression. Once you know the syntax, you reach for it constantly. This tutorial covers everything with practical examples.
Our sample data
{
"store": {
"books": [
{"title": "Clean Code", "price": 35, "inStock": true},
{"title": "The Pragmatic Programmer", "price": 45, "inStock": false},
{"title": "Refactoring", "price": 40, "inStock": true}
]
}
}The root: $
Every JSONPath expression starts with $, which represents the root of the document. From there you navigate with dots and brackets.
$ // the whole document
$.store // the store object
$.store.books // the books arrayAccessing array elements
$.store.books[0] // first book
$.store.books[-1] // last book
$.store.books[0,2] // first and third
$.store.books[0:2] // slice: first twoThe wildcard: *
[*] means "all elements." This is how you pull one field from every object without a loop:
$.store.books[*].title
// ["Clean Code", "The Pragmatic Programmer", "Refactoring"]Recursive descent: ..
The .. operator searches every level of the document. Use it when you do not know exactly where a key lives:
$..price // every price anywhere in the document
$..email // every email field at any depthThis is invaluable for exploring unfamiliar API schemas or debugging inconsistent nesting.
Filter expressions: ?()
The most powerful feature. ?() filters by a condition, where @ refers to the current element:
// All books in stock
$.store.books[?(@.inStock == true)]
// Books cheaper than 42
$.store.books[?(@.price < 42)]
// Combine conditions
$.store.books[?(@.price < 42 && @.inStock == true)]
// Check a key exists
$.store.books[?(@.discount)]Test JSONPath expressions in your browser
Paste your JSON, type a JSONPath query, and see matching results instantly. No install, no upload — free and private.
Why JSONPath beats writing loops
Compare extracting every in-stock book. Without JSONPath:
# Python — five lines, easy to get wrong
results = []
for book in data["store"]["books"]:
if book["inStock"]:
results.append(book)With JSONPath it is one self-documenting line: $.store.books[?(@.inStock == true)]. Anyone reading it immediately knows what you are after.
JSONPath vs jq vs JMESPath
- JSONPath — general-purpose querying. Best for extracting values in application code. Standardized in RFC 9535 (2024).
- jq — command-line tool with its own language. Most powerful, supports transformations, not just queries. Best for shell scripts.
- JMESPath — used by the AWS CLI. More rigorously specified. Best for AWS and consistent cross-platform use.
Library support
Use jsonpath-plus in JavaScript and jsonpath-ng in Python — together they cover 95% of use cases. Note that older libraries differ on edge cases like negative indices and recursive descent; RFC 9535 is improving interoperability. Standard JSONPath is read-only — for modifications, query first, then mutate with your language's native tools.