JSONPath Tutorial: Query and Extract JSON Data
A practical guide to querying and extracting data from JSON documents using JSONPath expressions. From basic property access to recursive descent and real-world patterns.
What Is JSONPath?
JSONPath is a query language for JSON, analogous to XPath for XML. It provides a concise syntax for selecting and extracting elements from a JSON document without writing procedural code. Originally proposed by Stefan Goessner in 2007, JSONPath has since been formalized as RFC 9535 (published 2024).
JSONPath is used in API testing tools (Postman, REST Assured), configuration systems (Kubernetes, AWS Step Functions), monitoring platforms, and data processing pipelines. Understanding it saves time whenever you need to extract specific values from complex JSON structures.
The Root Symbol: $
Every JSONPath expression starts with $, which represents the root of the JSON document. On its own, $ selects the entire document.
// Given this JSON:
{
"store": {
"books": [
{ "title": "The Pragmatic Programmer", "price": 49.99 },
{ "title": "Clean Code", "price": 39.99 },
{ "title": "Refactoring", "price": 44.99 }
],
"location": "online"
}
}
// $ selects the entire document
// $.store selects the "store" object
// $.store.location selects "online"Property Access
JSONPath supports two notations for accessing object properties:
Dot Notation
Dot notation is the most common and readable form. Use it when property names are simple identifiers (letters, digits, underscores).
$.store.location // "online"
$.store.books // the entire books arrayBracket Notation
Bracket notation is required when property names contain special characters, spaces, or start with a digit. It also allows using variables or expressions in some implementations.
$.store['books'] // same as $.store.books
$.['my-key'] // for keys with hyphens
$.['123'] // for keys that start with digitsArray Access
Arrays are accessed using bracket notation with numeric indices. JSONPath arrays are zero-indexed.
$.store.books[0] // first book
$.store.books[2] // third book
$.store.books[-1] // last book (negative indexing)
$.store.books[0,2] // first and third booksArray Slicing
JSONPath supports Python-style array slicing with the syntax [start:end:step]. The end index is exclusive.
$.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 (step of 2)Wildcards
The wildcard operator * selects all elements at the current level. It works on both objects (all values) and arrays (all items).
$.store.books[*] // all books in the array
$.store.books[*].title // all book titles
$.store.* // all values in the store objectThis is particularly useful for extracting a specific field from every item in an array, such as all names from a list of users or all IDs from API results.
Recursive Descent
The double-dot operator .. performs a recursive descent through the entire document, finding all occurrences of the specified key at any nesting depth.
$..price // all "price" values at any depth
$..title // all "title" values at any depth
// Given deeply nested data:
{
"company": {
"departments": [
{
"name": "Engineering",
"teams": [
{ "name": "Frontend", "lead": "Alice" },
{ "name": "Backend", "lead": "Bob" }
]
}
]
}
}
$..name // ["Engineering", "Frontend", "Backend"]
$..lead // ["Alice", "Bob"]Recursive descent is powerful but can be expensive on large documents since it traverses the entire structure. Use it when you do not know the exact path to a value or when the value appears at multiple depths.
Quick Reference Table
| Expression | Description |
|---|---|
| $ | Root of the document |
| $.key | Direct child property |
| $['key'] | Bracket notation (for special chars) |
| $.array[0] | Array index (zero-based) |
| $.array[-1] | Last element (negative index) |
| $.array[0:3] | Array slice (indices 0, 1, 2) |
| $.array[*] | All array elements |
| $..key | Recursive descent (any depth) |
| $.* | All properties of root object |
JSONPath vs jq
Both JSONPath and jq solve the problem of querying JSON, but they take different approaches. JSONPath is a query language embedded in other tools, while jq is a standalone command-line processor with its own programming language.
| Task | JSONPath | jq |
|---|---|---|
| Get a property | $.name | .name |
| Array index | $.items[0] | .items[0] |
| All array items | $.items[*].name | .items[].name |
| Recursive search | $..name | .. | .name? // empty |
| Transform output | Not supported | {name, age} |
Use JSONPath when you are working within a tool that supports it (Postman, Kubernetes, AWS Step Functions). Use jq when you need to transform JSON on the command line or in shell scripts.
Real-World Use Cases
API Response Filtering
When testing APIs, JSONPath extracts the specific fields you need to verify from large response bodies:
// GitHub API response for repository search
// Extract all repository names
$.items[*].full_name
// Extract the first result's star count
$.items[0].stargazers_count
// Get all topics across all results
$.items[*].topics[*]Configuration Extraction
In configuration management, JSONPath selects specific values from complex config files:
// AWS CloudFormation template
// Get all resource types
$.Resources.*.Type
// Get all Lambda function ARNs
$..FunctionArnData Pipeline Processing
In data pipelines, JSONPath expressions define which fields to extract, transform, or aggregate from incoming JSON events:
// Extract user events from a mixed event stream
$[?(@.type=='user_event')].payload
// Get all timestamps from nested log entries
$..timestamp
// Select specific fields from an array of records
$.records[*].['id','email','created_at']Try JSONPath Queries
Our JSON Formatter includes a built-in JSONPath query executor. Paste your JSON, switch to the Transform tab, and enter any JSONPath expression to see matching results instantly. Supported expressions include dot notation, bracket notation, wildcards, and recursive descent. Everything runs in your browser with no data sent to any server.
For understanding the structure of your JSON before writing queries, the Tree View and Stats tabs provide a visual breakdown of your document's structure, depth, and key frequency. This context makes it easier to construct accurate JSONPath expressions.
Further Reading
- RFC 9535 — JSONPath
The IETF standard for JSONPath query expressions for JSON.
- JSONPath — Stefan Goessner
The original article that introduced JSONPath notation.
- jq manual
Documentation for jq, the popular command-line JSON processor.