JSONPath Cheatsheet: 20 Expressions Every Developer Needs
JSONPath is to JSON what XPath is to XML — a small query language for reaching into deeply-nested data and pulling out exactly what you need. Once you've written more than a few nested for-loops to walk an API response, JSONPath starts to feel like a superpower. This cheatsheet covers the 20 expressions you'll use 95% of the time, with runnable examples you can paste into any JSONPath tester.
The sample JSON we'll use
Every example below runs against this store data:
{
"store": {
"books": [
{ "title": "The Pragmatic Programmer", "author": "Hunt", "price": 39.95, "inStock": true, "tags": ["classic", "dev"] },
{ "title": "Clean Code", "author": "Martin", "price": 29.99, "inStock": true, "tags": ["dev"] },
{ "title": "Design Patterns", "author": "GoF", "price": 44.95, "inStock": false, "tags": ["classic"] },
{ "title": "Refactoring", "author": "Fowler", "price": 34.99, "inStock": true, "tags": ["dev"] }
],
"location": { "city": "San Francisco", "country": "USA" }
},
"members": 1240
}1. The basics — $ and dot notation
$ is the root of your document. Chain keys with dots to drill in.
$ → the whole document
$.store → the store object
$.store.location.city → "San Francisco"
$.members → 12402. Array indexing
Use square brackets for arrays. Indexes are zero-based, and negative indexes count from the end.
$.store.books[0] → first book
$.store.books[-1] → last book
$.store.books[0].title → "The Pragmatic Programmer"3. Wildcards — [*] and .*
Wildcards return every child. This is how you 'unwrap' an array without knowing its length.
$.store.books[*] → every book (array of 4 objects)
$.store.books[*].title → ["The Pragmatic Programmer", "Clean Code", ...]
$.store.* → every value directly under store4. Array slicing
Same syntax as Python slicing — [start:end:step], end exclusive.
$.store.books[0:2] → first two books
$.store.books[1:] → all but the first
$.store.books[::2] → every other book (indexes 0, 2)5. Recursive descent — ..
Two dots mean 'find this key anywhere below here, at any depth.' Extremely useful when you don't know the exact path.
$..title → every 'title' key anywhere in the doc
$..price → every 'price' key
$.store..city → 'city' anywhere under store6. Filter expressions — [?(...)]
The killer feature. Filters keep only the items matching a boolean expression. @ refers to the current item being filtered.
$.store.books[?(@.price < 35)] → books cheaper than $35
$.store.books[?(@.inStock == true)] → books in stock
$.store.books[?(@.author == "Fowler")] → books by Fowler
$.store.books[?(@.price >= 30 && @.price <= 40)] → mid-priced books7. Combine filters with wildcards
Filters produce arrays, so you can keep chaining.
$.store.books[?(@.inStock)].title → titles of in-stock books
$.store.books[?(@.price > 30)].author → authors of pricier books8. Check for a key's existence
In many implementations, referencing @.key inside a filter returns falsy when the key is missing.
$..books[?(@.discount)] → only books that have a 'discount' field9. String matches and regex (implementation-dependent)
Not every JSONPath library supports these, but jsonpath-plus and Goessner-flavored parsers usually do.
$..books[?(@.title =~ /clean/i)] → titles containing 'clean' (case-insensitive)
$..books[?(@.tags.indexOf('dev') > -1)] → tagged 'dev'10. The union operator — [a, b]
Pick multiple specific children in one query.
$.store.books[0, 2] → first and third book
$.store.books[*]['title', 'price'] → title and price of every bookCommon traps
- Filters must be wrapped in [?(...)] — the ? and parentheses are required.
- Recursive descent (..) is powerful but slow on huge documents — prefer explicit paths when you know them.
- JSONPath is not standardized. Different libraries handle edge cases differently (especially script expressions and regex). Test in the library you'll actually ship with.
- @ is the current item inside a filter — it's easy to confuse with $ (the root).
- Slice syntax uses colons (0:2), not commas — commas are the union operator.
Test any of these in seconds
Paste your JSON and try the expressions above in our free JSONPath tester — it runs entirely in your browser, no data leaves your device, and results highlight in real time. Perfect for exploring an unfamiliar API response.
Try it yourself
JSONPath Tester