JSONPath Query Guide: How to Search JSON Data
JSON has become the universal language of the web. APIs return JSON, configuration files use JSON, and databases store JSON documents. But as JSON structures grow larger and more deeply nested, finding specific values becomes increasingly difficult. That is where JSONPath comes in. JSONPath is a query language that lets you navigate and extract data from JSON documents using concise path expressions, much like XPath does for XML. This guide covers everything from basic syntax to advanced filtering, with practical examples you can apply immediately.
What Is JSONPath?
JSONPath is a query language for JSON that was originally proposed by Stefan Goessner in 2007. It provides a compact syntax for selecting nodes from a JSON document, similar to how CSS selectors target HTML elements or XPath expressions locate XML nodes. Instead of writing loops and conditional logic to traverse a JSON structure, you write a single expression that describes the path to the data you want.
JSONPath expressions start from the root of the JSON document and navigate through objects and arrays to reach the desired values. The language supports wildcards, recursive descent, array slicing, and filter expressions, making it powerful enough for most data extraction needs.
The Sample JSON Document
Throughout this guide, we will use the following JSON document as our working example. This is the classic example from the original JSONPath proposal, adapted with additional data:
{
"store": {
"book": [
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{
"category": "fiction",
"author": "J.R.R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
}
}
JSONPath Syntax Reference
JSONPath uses a small set of operators that combine to form powerful queries. Here is the complete syntax reference:
| Operator | Description | Example |
|---|---|---|
$ |
Root node of the document | $ |
. |
Child operator (access object property) | $.store |
[] |
Array index or child operator | $.store.book[0] |
[*] |
Wildcard for all array elements | $.store.book[*] |
.. |
Recursive descent (search all levels) | $..author |
.key |
Named object property | $.store.bicycle |
['key'] |
Bracket notation for property access | $['store']['book'] |
[start:end] |
Array slice (end is exclusive) | $.store.book[0:2] |
[?()]code> |
Filter expression | $.store.book[?(@.price < 10)] |
() |
Script expression (implementation-dependent) | $.store.book[(@.length-1)] |
Basic JSONPath Expressions
Accessing the Root and Direct Children
The dollar sign $ represents the root of the JSON document. From there, you navigate using dot notation for object properties and bracket notation for array indices.
| Expression | Result |
|---|---|
$ |
The entire JSON document |
$.store |
The store object (contains book array and bicycle object) |
$.store.bicycle |
{"color": "red", "price": 19.95} |
$.store.bicycle.color |
"red" |
$.store.book |
The entire book array |
$.store.book[0] |
The first book object |
$.store.book[0].title |
"Sayings of the Century" |
$.store.book[3].author |
"J.R.R. Tolkien" |
Bracket Notation
Bracket notation is an alternative to dot notation that is useful when property names contain special characters, spaces, or start with numbers:
$.store['book'][0]['title']
$['store']['bicycle']['color']
Bracket notation and dot notation are interchangeable for object properties. However, bracket notation is required when the property name is dynamic or contains characters that are not valid in dot notation.
Wildcard Operator
The wildcard operator * matches all elements in an array or all properties in an object. It is incredibly useful for extracting all values at a certain level without knowing the specific keys or indices.
| Expression | Result |
|---|---|
$.store.* |
All values in the store object (book array and bicycle object) |
$.store.book[*] |
All books in the array (all four book objects) |
$.store.book[*].author |
All author names: ["Nigel Rees", "Evelyn Waugh", "Herman Melville", "J.R.R. Tolkien"] |
$.store.*.price |
Prices of bicycle and the book array (not individual book prices) |
Recursive Descent: The Double Dot Operator
The double dot operator .. is one of the most powerful JSONPath features. It searches for the specified key at every level of the JSON tree, not just the immediate children. Think of it as a deep search through the entire document.
| Expression | Result |
|---|---|
$..author |
All author values anywhere in the document |
$..price |
All price values: [8.95, 12.99, 8.99, 22.99, 19.95] |
$..book[2] |
The third book, found recursively |
$..category |
All category values: ["reference", "fiction", "fiction", "fiction"] |
The recursive descent operator is particularly useful when you do not know the exact path to the data you need, or when the same key appears at multiple levels of nesting. For example, if an API response contains id fields at various nesting levels, $..id collects them all.
Array Slicing
Array slicing lets you select a range of elements from an array. The syntax [start:end] selects elements from the start index up to (but not including) the end index. Both positive and negative indices are supported.
| Expression | Result |
|---|---|
$.store.book[0:2] |
First two books (indices 0 and 1) |
$.store.book[1:3] |
Second and third books (indices 1 and 2) |
$.store.book[-1] |
Last book (The Lord of the Rings) |
$.store.book[-2:] |
Last two books |
$.store.book[:2] |
First two books (same as [0:2]) |
$.store.book[2:] |
Third book onwards |
Note that slice behavior can vary slightly between JSONPath implementations. The syntax above follows the conventions used by most popular libraries and the IETF RFC 9535 standard.
Filter Expressions
Filter expressions are where JSONPath becomes truly powerful. They let you select elements based on conditions rather than positions. The filter syntax uses [?(condition)], where the condition is evaluated for each element.
Comparison Operators
JSONPath supports the following comparison operators in filter expressions:
| Operator | Meaning | Example |
|---|---|---|
== |
Equal to | [?(@.category == "fiction")] |
!= |
Not equal to | [?(@.category != "fiction")] |
< |
Less than | [?(@.price < 10)] |
<= |
Less than or equal to | [?(@.price <= 8.99)] |
> |
Greater than | [?(@.price > 15)] |
>= |
Greater than or equal to | [?(@.price >= 12.99)] |
=~ |
Regex match (some implementations) | [?(@.author =~ /Tolkien/i)] |
Practical Filter Examples
Using our sample document, here are practical filter expressions and their results:
Find all books cheaper than $10:
$.store.book[?(@.price < 10)]
Returns the books "Sayings of the Century" ($8.95) and "Moby Dick" ($8.99).
Find all fiction books:
$.store.book[?(@.category == "fiction")]
Returns three books: "Sword of Honour", "Moby Dick", and "The Lord of the Rings".
Find books with an ISBN:
$.store.book[?(@.isbn)]
Returns books that have an isbn property: "Moby Dick" and "The Lord of the Rings". This works because the filter checks for the existence of the property.
Find the most expensive book:
$.store.book[?(@.price > 20)]
Returns "The Lord of the Rings" ($22.99).
Logical Operators in Filters
You can combine conditions using logical operators:
$.store.book[?(@.price < 10 && @.category == "fiction")]
$.store.book[?(@.price > 15 || @.category == "reference")]
The first expression finds fiction books under $10 (only "Moby Dick"). The second finds books that are either over $15 or in the reference category (returns "Sayings of the Century" and "The Lord of the Rings").
JSONPath vs XPath
JSONPath was explicitly modeled after XPath, and the two languages share many conceptual similarities. Understanding the relationship helps if you are familiar with XML processing.
| Feature | JSONPath | XPath |
|---|---|---|
| Root symbol | $ |
/ |
| Child access | .key or ['key'] |
/element |
| Array index | [0] |
[1] (1-based) |
| Wildcard | * |
* |
| Recursive descent | .. |
// |
| Filter | [?(condition)] |
[condition] |
| Attributes | Not applicable (JSON has no attributes) | @attr |
| Current node | @ (in filters) |
. or current() |
| Parent | Not supported | .. |
| Axes | Not supported | 13 axes (ancestor, following, etc.) |
| Data model | Objects and arrays | Elements, attributes, text nodes |
The key difference is that XPath operates on a rich tree model with elements, attributes, text nodes, namespaces, and processing instructions. JSONPath operates on a simpler model of objects (key-value maps) and arrays (ordered lists). This simplicity makes JSONPath easier to learn but less expressive than XPath for complex queries.
JSONPath in Practice
API Testing
JSONPath is indispensable for API testing. When you send a request to an API and receive a large JSON response, JSONPath lets you assert specific values without navigating the entire structure manually. Most API testing tools support JSONPath natively.
For example, in a test you might verify that the first book's price is less than $10:
// Using a JSONPath assertion in testing
response.jsonPath().get("store.book[0].price").should(equals(8.95));
// Find all books by a specific author
response.jsonPath().get("store.book[?(@.author == 'Herman Melville')].title");
// Returns: ["Moby Dick"]
Data Transformation
When integrating systems that use different data formats, JSONPath helps extract and transform specific fields. You can pull values from one JSON structure and map them to another without writing complex traversal code.
Configuration Management
Complex configuration files often contain deeply nested JSON. JSONPath lets you query specific configuration values without loading and parsing the entire structure. Tools like jq use JSONPath-like syntax for processing JSON in command-line pipelines.
Monitoring and Alerting
In observability systems, JSONPath queries can extract metrics from JSON-formatted logs and API responses. You can set up alerts that trigger when a JSONPath query returns values exceeding thresholds.
JSONPath Implementations
JSONPath is available in virtually every programming language. Here are the most popular libraries:
| Language | Library | Installation |
|---|---|---|
| JavaScript | jsonpath-plus | npm install jsonpath-plus |
| Python | jsonpath-ng | pip install jsonpath-ng |
| Java | JsonPath (Jayway) | Maven: com.jayway.jsonpath |
| C# | Json.NET (Newtonsoft) | NuGet: Newtonsoft.Json |
| Go | gjson | go get github.com/tidwall/gjson |
| PHP | jsonpath | composer require softcreatr/jsonpath |
| Ruby | jsonpath | gem install jsonpath |
JavaScript Example
import { JSONPath } from 'jsonpath-plus';
const data = { /* our sample JSON */ };
const authors = JSONPath({ path: '$..author', json: data });
// ["Nigel Rees", "Evelyn Waugh", "Herman Melville", "J.R.R. Tolkien"]
const cheapBooks = JSONPath({
path: '$.store.book[?(@.price < 10)]',
json: data
});
// Returns books with price < 10
Python Example
from jsonpath_ng import parse
data = { /* our sample JSON */ }
# Find all authors
author_expr = parse('$..author')
authors = [match.value for match in author_expr.find(data)]
# ["Nigel Rees", "Evelyn Waugh", "Herman Melville", "J.R.R. Tolkien"]
# Find cheap books
cheap_expr = parse('$.store.book[?(@.price < 10)]')
cheap_books = [match.value for match in cheap_expr.find(data)]
Common Pitfalls and Tips
- Zero-based vs one-based indexing: JSONPath uses zero-based indexing (the first element is [0]), while XPath uses one-based indexing (the first element is [1]). This is a common source of off-by-one errors.
- Implementation differences: Before the IETF standard (RFC 9535), JSONPath implementations varied in their handling of edge cases like empty results, null values, and filter syntax. Always test your expressions with the specific library you are using.
- Filter performance: Recursive descent with filters (
$..book[?(@.price < 10)]) can be slow on large documents because it must traverse the entire tree. For performance-critical applications, use more specific paths when possible. - Case sensitivity: JSONPath is case-sensitive.
$.Storewill not match$.store. This is consistent with JSON's case-sensitive nature. - Escaping special characters: If a key name contains dots or brackets, you must use bracket notation with quotes:
$['key.with.dots']instead of$.key.with.dots. - No parent traversal: Unlike XPath, JSONPath cannot navigate to parent nodes. There is no equivalent to XPath's
..(parent axis). JSONPath's..means recursive descent, not parent.
$.store, verify it works, then extend it step by step: $.store.book, then $.store.book[*], then $.store.book[*].price, and finally add your filter. This makes debugging much easier.
The IETF Standard: RFC 9535
In 2024, the IETF published RFC 9535, which formally standardizes JSONPath. This specification resolves many of the ambiguities and inconsistencies that existed across implementations. Key aspects of the standard include:
- Defined semantics: Precise rules for how each operator behaves, including edge cases like missing keys, null values, and type mismatches in comparisons.
- Normalized syntax: A canonical form for JSONPath expressions that all conforming implementations must support.
- Filter expression specification: Clear rules for filter syntax, including which comparison and logical operators are supported.
- Function extensions: A mechanism for extending JSONPath with custom functions like
length(),count(), andmatch().
If you are starting a new project, prefer libraries that implement RFC 9535 for maximum compatibility and predictable behavior.
Need to query JSON data quickly? Try our free online JSONPath tester to evaluate expressions against your JSON documents in real time.
Try JSONPath FinderFrequently Asked Questions
What is JSONPath?
JSONPath is a query language for JSON, similar to XPath for XML. It uses path expressions to navigate and extract specific values from JSON documents. JSONPath expressions like $.store.book[0].title let you pinpoint exact data within complex nested JSON structures without writing custom parsing code.
How is JSONPath different from XPath?
JSONPath is designed for JSON's object and array structure, while XPath is designed for XML's tree of elements and attributes. JSONPath uses $ as the root, dot notation for object access, and bracket notation for arrays. XPath uses / for path separation and @ for attributes. JSONPath is simpler but less feature-rich than XPath.
What does the double dot (..) mean in JSONPath?
The double dot (..) in JSONPath is the recursive descent operator. It searches for the named key at all levels of the JSON structure, not just the immediate children. For example, $..author finds all author keys anywhere in the entire document, regardless of how deeply nested they are.
Can JSONPath filter data based on conditions?
Yes, JSONPath supports filter expressions using the syntax [?(condition)]. You can filter array elements based on their property values using comparison operators like ==, !=, <, >, <=, >= and logical operators like && and ||. For example, $.store.book[?(@.price < 10)] finds all books cheaper than $10.
Is JSONPath standardized?
JSONPath was originally proposed by Stefan Goessner in 2007 without a formal specification, leading to variations across implementations. In 2024, IETF published RFC 9535 which formally standardizes JSONPath. Modern implementations are converging on this standard, but some older libraries may still have minor syntax differences.