JSONPath: The Complete Guide to Querying JSON Data
JSONPath is a query language for JSON, analogous to XPath for XML. It lets you navigate into complex, deeply nested JSON structures and extract exactly the values you need using a concise path expression. Whether you are filtering API responses, writing test assertions, or transforming data pipelines, JSONPath is an essential tool to have in your toolkit.
JSONPath Basics: The Root and Dot Notation
Every JSONPath expression starts with $, which represents the root of the JSON document. From there, you navigate using dots (.) for child access or square brackets ([]) for subscript access.
{
"store": {
"name": "The Bookstore",
"books": [
{ "title": "Clean Code", "author": "Robert Martin", "price": 29.99, "inStock": true },
{ "title": "The Pragmatic Programmer", "author": "Hunt & Thomas", "price": 39.99, "inStock": false },
{ "title": "Refactoring", "author": "Martin Fowler", "price": 34.99, "inStock": true }
],
"location": {
"city": "New York",
"zip": "10001"
}
}
}| Expression | Result |
|---|---|
| $ | The entire document |
| $.store.name | "The Bookstore" |
| $.store.location.city | "New York" |
| $.store.books[0] | First book object |
| $.store.books[0].title | "Clean Code" |
| $.store.books[-1] | Last book (Refactoring) |
| $.store.books[0,1] | First two books |
| $.store.books[0:2] | Books at index 0 and 1 (slice) |
Wildcards: Selecting All Children
The wildcard * matches any child element. Use it to select all items in an array or all properties of an object.
$.store.books[*] → all books (array of 3 objects)
$.store.books[*].title → ["Clean Code", "The Pragmatic Programmer", "Refactoring"]
$.store.books[*].price → [29.99, 39.99, 34.99]
$.store.* → all values under "store" (books array + location object + name)Recursive Descent: Searching Deep Structures
The double-dot operator .. (recursive descent) searches the entire document tree for a key, regardless of depth. This is extremely useful when you don't know exactly how deep a value is nested.
$..title → all "title" values anywhere in the document
$..price → all "price" values at any depth
$..books[0].title → "title" of the first element of any "books" array found anywhereFilter Expressions: Conditional Selection
Filter expressions use the syntax [?()] to select array elements that satisfy a condition. Use @ to refer to the current element.
$.store.books[?(@.inStock == true)]
→ [{ "title": "Clean Code", ... }, { "title": "Refactoring", ... }]
$.store.books[?(@.price < 35)]
→ [{ "title": "Clean Code", "price": 29.99 }, { "title": "Refactoring", "price": 34.99 }]
$.store.books[?(@.author =~ /Martin/)]
→ books where author contains "Martin" (regex, supported by some implementations)
$.store.books[?(@.price >= 30 && @.inStock == true)]
→ books costing $30+ that are in stockTest your JSONPath expressions live
Use our JSONPath Tool to paste your JSON and run expressions interactively. Results are highlighted in the tree view instantly.
Bracket Notation vs Dot Notation
Both notations are equivalent for simple property access. Use bracket notation when a key contains spaces, hyphens, or other special characters that would break dot notation.
$.store.name ← dot notation
$['store']['name'] ← bracket notation (equivalent)
$['store']['location']['city'] ← required for keys with spaces:
$['user-agent'] ← key with hyphen — dot notation would fail
$['@context'] ← key starting with @ (common in JSON-LD)JSONPath in Different Languages
import { JSONPath } from 'jsonpath-plus';
const result = JSONPath({ path: '$.store.books[?(@.inStock==true)].title', json: data });
// → ["Clean Code", "Refactoring"]from jsonpath_ng import parse
expr = parse('$.store.books[?(@.inStock == true)].title')
matches = [match.value for match in expr.find(data)]
# → ["Clean Code", "Refactoring"]# jq uses a different but similar syntax
cat data.json | jq '.store.books[] | select(.inStock == true) | .title'
# → "Clean Code"
# "Refactoring"JSONPath vs jq: What's the Difference?
| Feature | JSONPath | jq |
|---|---|---|
| Standard | RFC 9535 (2024) | No formal standard |
| Language support | Many libraries in JS, Python, Java, Go... | CLI tool + some libraries |
| Syntax | $.store.books[*].title | .store.books[].title |
| Filter expressions | [?(@.price < 35)] | select(.price < 35) |
| Best for | Programmatic queries inside apps | CLI data wrangling and shell scripts |
| Output | Array of matched values | Streaming newline-delimited values |
Common JSONPath Patterns
- Get all IDs:
$..id— find everyidfield recursively - First N items:
$.items[0:5]— array slice, first 5 elements - Last item:
$.items[-1]— last element of an array - Nested filter:
$.users[?(@.address.country == 'US')] - Multiple keys:
$.books[*]['title','author']— select only title and author - Check key exists:
$.items[?(@.discount)]— items where 'discount' key exists
Run JSONPath expressions on your JSON
Paste any JSON document and write JSONPath queries interactively. Results update instantly as you type.