How to Query JSON with JSONPath: A Practical Guide
JSONPath lets you extract exactly the values you need from a JSON document without writing a parser. This guide covers the syntax and shows how to test expressions instantly.
Digging a single value out of a deeply nested API response usually means writing a chain of obj.data.items[0].meta.tags and hoping the shape never changes. JSONPath solves this differently: instead of hardcoding a route through the document, you describe a pattern - wildcards, conditions, recursive lookups - and let the query engine find every match, wherever it lives.
This guide walks through JSONPath syntax from the basics to filter expressions, and shows where each piece is useful in real work. You can follow along with the JSONPath Evaluator, which runs every query locally in your browser and shows live matches as you type.
What is JSONPath?
JSONPath is a small query language for JSON, similar in spirit to XPath for XML. A JSONPath expression is a string like $.store.book[*].author that, when evaluated against a document, returns every value matching that pattern - not just one hardcoded location.
The $ always refers to the root of the document. From there you chain child selectors (.book), wildcards ([*]), array indices, slices, and filter conditions to zero in on the data you actually want. The result is a list of matches, because a single expression can legitimately match zero, one, or many values.
Selecting nested authors
A JSONPath query pulling one field out of every item in an array, regardless of how many books there are.
Input
{
"store": {
"book": [
{ "title": "A", "author": "Kay" },
{ "title": "B", "author": "Ng" }
]
}
}Output
// $.store.book[*].author
["Kay", "Ng"]Why use JSONPath instead of manual traversal
Writing data.results[0].user.email works until the API returns zero results, or the field you want is buried under an array whose length varies. JSONPath expressions describe the shape of what you are looking for rather than a fixed sequence of property accesses, so they hold up better against real-world data variability.
- Resilience to shape changes - a wildcard or recursive selector still finds matches even when array lengths or nesting shift.
- Portability - the same expression syntax is understood by libraries in Python, Java, JavaScript, and by tools like
jq-adjacent query engines, so a query you validate once travels with you. - Readability -
$.orders[?(@.status == "paid")].totalreads closer to a sentence than five lines of nested loops and conditionals. - Fast prototyping - you can try an expression against a real payload in the JSONPath Evaluator before wiring it into application code, a test, or a data pipeline.
Core JSONPath syntax you will use daily
A handful of operators cover almost every practical query. The JSONPath Evaluator supports all of them, along with clear error messages when an expression is malformed.
Root and child access
$ is the document root. .key or ['key'] moves into a child property. $.store.book walks two levels deep to reach the book array.
Wildcards and recursive descent
[*] matches every element of an array or every value in an object, regardless of key name. .. is recursive descent - it searches at every depth, not just the immediate children. $..author finds an author field no matter how deeply it is nested, which is invaluable when you do not know or do not want to hardcode the exact path.
Array indices and slices
[0] returns the first element, [-1] the last. [0:2] slices a range, similar to Python or JavaScript array slicing. [0,2] is a union that returns the first and third elements together.
Filter expressions
Filters select array elements matching a condition, using @ to refer to the current item being tested. $.books[?(@.price < 10)] returns every book priced under ten. Comparisons support the usual operators, and filters can be combined with property access afterward, such as $.books[?(@.price < 10)].title to get just the titles.
$.store.book[*].author -> every author
$..price -> every price at any depth
$.store.book[0:2] -> the first two books
$.store.book[?(@.price < 10)] -> books cheaper than 10Step-by-step: testing a JSONPath expression
- Open the JSONPath Evaluator and paste the JSON document you want to query.
- Write a JSONPath expression, starting simple - for example
$.items[*].name- to target the values you need. - Watch the results update live, with each match shown alongside the exact path it was found at in the document.
- Refine the expression with a filter, slice, or wildcard if the first pass returns too much or too little.
- Copy the matched results as a JSON array to paste into code, a test fixture, or documentation.
Your data stays on your device
Because evaluating a JSONPath expression is pure computation - matching a pattern against a data structure - it never needs a server. The JSONPath Evaluator runs entirely in your browser, so it is safe to query API responses, internal configs, or documents containing customer records without anything being uploaded or logged.
Common use cases
- Extracting a specific field from a large, deeply nested API response without writing custom traversal code.
- Prototyping the exact JSONPath expression you plan to hardcode into a config file, pipeline step, or monitoring rule.
- Filtering array items by a condition such as price, status, or a boolean flag before processing them further.
- Pulling every value at a given key regardless of how deep it appears, using recursive descent.
- Debugging why a JSONPath selector unexpectedly returns no matches against real data.
Common mistakes and how to avoid them
Mixing up dot and bracket syntax
.key only works when the key is a valid identifier with no spaces or special characters. A key like "user-id" or "first name" needs bracket notation instead: ['user-id']. Forgetting this is a frequent source of a query silently returning nothing.
Expecting a single value instead of a list
JSONPath always returns a collection of matches, even when exactly one value matches. Code that expects a scalar needs to explicitly take the first element, otherwise you will end up comparing or serializing an array by mistake.
Overusing recursive descent
$..name is convenient, but on a large document with many objects that happen to share a key name, it can return far more matches than intended. Scope the query with an explicit path segment first, such as $.users..name, when you know roughly where the values live.
Filter comparisons and quoting
String comparisons inside a filter, like @.status == "active", need the string value quoted. Comparing a string field against an unquoted bareword is a common typo that produces zero matches instead of an error, so double-check the result count matches what you expect.
Best practices for writing JSONPath
- Build expressions incrementally: start with a broad selector, confirm it matches something, then narrow it with a filter or index.
- Test against real, representative data rather than a trimmed-down sample - edge cases like empty arrays or missing keys often reveal a broken assumption.
- Keep expressions as specific as practical; a narrower path is easier to read later and less likely to match unrelated data as the document evolves.
- When you need the whole document reshaped rather than a subset extracted, reach for flattening or a tree view instead - JSONPath is for selective extraction, not restructuring.
- Save expressions you rely on regularly as inline comments near the code that uses them, since the intent behind a terse selector is not always obvious months later.
Related tools
Explore JSON as a collapsible, interactive tree.
Flatten nested JSON into single-level dot-notation key paths.
Pretty-print JSON with configurable indentation and instant validation.
Validate JSON against a JSON Schema using AJV.
Related guides
Raw JSON text hides its own shape. This guide shows how a collapsible tree view turns an unfamiliar payload into something you can scan, search, and navigate in seconds.
Nested JSON is hard to drop into a spreadsheet, an .env file, or a flat key-value store. This guide explains how flattening converts nested structures into dot-notation keys, when to use it, and the mistakes to avoid.
Minified JSON is unreadable and hard to debug. This guide covers how JSON formatting works, when to use it, common mistakes, and how to pretty-print JSON without uploading it anywhere.
A JSON document can be well-formed and still be wrong. This guide explains JSON Schema validation, how AJV catches contract violations, and how to check your data with precise, path-level errors.