JSONPath is the XPath of the JSON world — a compact language for extracting values from JSON documents. This tutorial covers every JSONPath operator with practical examples you can run in our JSONPath tester.
Why JSONPath exists
When you have a JSON response from an API and need a specific subset — all user emails, every product over $100, the third element of the second array — you have two options. Write nested loops and conditionals in your code, or write a single JSONPath expression.
JSONPath is much shorter. Compare:
// Imperative
const emails = [];
for (const user of data.users) {
if (user.active) emails.push(user.email);
}
// JSONPath
$.users[?(@.active==true)].email
For complex extractions, JSONPath is dramatically more compact than the equivalent code.
Operators reference
Every JSONPath expression starts with $, the root of the document. Operators chain after it.
| Operator | Meaning | Example |
|---|---|---|
$ | Root | $ |
.name | Child by name | $.user.name |
['name'] | Child by name (bracket) | $['key-with-dash'] |
[*] | Wildcard (all) | $.users[*] |
.. | Recursive descent | $..price |
[2] | Array index | $.items[0] |
[a:b] | Slice | $.items[0:3] |
[?()] | Filter | $.users[?(@.age>18)] |
[a,b] | Union | $['name','email'] |
Working example
We'll use this dataset throughout:
{
"store": {
"books": [
{ "title": "Norwegian Wood", "author": "Murakami", "price": 12.99, "isbn": "978-0099448822" },
{ "title": "Brave New World", "author": "Huxley", "price": 9.99 },
{ "title": "1984", "author": "Orwell", "price": 14.50, "isbn": "978-0452284234" },
{ "title": "The Trial", "author": "Kafka", "price": 8.50 }
],
"bicycle": {
"color": "red",
"price": 199.99
}
}
}
Basic child access
$.store.bicycle.color → "red"
$.store.books[0].title → "Norwegian Wood"
All elements of an array
$.store.books[*].title → ["Norwegian Wood", "Brave New World", "1984", "The Trial"]
Recursive descent
$..price → [12.99, 9.99, 14.50, 8.50, 199.99] — every "price" field anywhere in the tree.
Slices (Python-style)
$.store.books[0:2] → first two books
$.store.books[-2:] → last two books
$.store.books[::2] → every other book (step 2)
Filters
$.store.books[?(@.price < 10)] → books cheaper than $10
$.store.books[?(@.isbn)] → books that have an ISBN field
$.store.books[?(@.author=="Orwell")].title → titles by Orwell
Filter expressions support: ==, !=, <, <=, >, >=, and logical &&, || (in most implementations).
Unions
$.store.books[0,2].title → titles of books 0 and 2
$.store.books[*]['title','price'] → title and price of every book
Real-world examples
Extract all error messages from a nested response:
$..error
Get the email of every active user:
$.users[?(@.active==true)].email
Get product names in stock under $100:
$.products[?(@.stock>0 && @.price<100)].name
Get the last 3 orders:
$.orders[-3:]
Get cities of every user's address:
$.users[*].address.city
JSONPath vs jq
jq is more powerful — it can transform and aggregate, not just select. The same query in both:
# JSONPath
$.users[?(@.active==true)].email
# jq
.users[] | select(.active==true) | .email
For pure extraction, JSONPath is simpler to learn. For complex pipelines that need filtering, mapping, and aggregation, jq is more capable. They aren't replacements — they're complementary tools.
JSONPath vs JMESPath
JMESPath is AWS's preferred JSON query language, used in the AWS CLI's --query parameter. The syntax is similar but not identical. JMESPath is more structured (and has a formal spec) but less widely supported. If you work primarily with AWS tools, learn JMESPath. Otherwise, JSONPath is the safer bet.
Dialect variations
JSONPath was specified informally by Stefan Goessner in 2007. Most implementations follow that informal spec, but they diverge on details:
- Some support functions like
length()andmin(); most don't. - Some require
@in filters explicitly; some allow plain property names. - Some treat single results as arrays; some unwrap them.
IETF RFC 9535 (2024) formalizes a strict subset. As implementations adopt it, dialect variations should reduce.
Testing your expressions
The fastest way to learn JSONPath is to experiment. Our JSONPath tester shows results instantly as you type the expression — paste a sample JSON, then try different paths to see what matches. After 10 minutes of play, the syntax becomes second nature.
Wrap-up
JSONPath is one of the highest-leverage skills for anyone who consumes JSON APIs. A few minutes of learning saves hours of writing extraction loops. Start with the basic operators (., [*], ..) — they cover 80% of real queries. Add filters when you need conditional selection.