Enter a JSONPath expression to extract matching values from your JSON:
What is JSONPath?
JSONPath is XPath for JSON—a query language that lets you extract values from JSON documents using path expressions. Instead of writing loops to find data, you write a single expression like $.users[*].email to get all user emails.
Syntax Quick Reference
| Expression | Description | Example |
|---|---|---|
$ | Root object | $ → entire document |
. | Child property | $.store → store object |
.. | Recursive descent (find anywhere) | $..price → all prices |
[n] | Array index | $.items[0] → first item |
[*] | All elements | $.items[*] → all items |
[-1] | Last element | $.items[-1] → last item |
[0:3] | Array slice | $.items[0:3] → first 3 items |
[?(@.x)] | Filter expression | $..book[?(@.price<10)] |
Working Example
Consider this API response:
{
"store": {
"name": "TechMart",
"products": [
{ "id": 1, "name": "Laptop", "price": 999, "inStock": true },
{ "id": 2, "name": "Mouse", "price": 29, "inStock": true },
{ "id": 3, "name": "Keyboard", "price": 79, "inStock": false },
{ "id": 4, "name": "Monitor", "price": 299, "inStock": true }
],
"location": {
"city": "San Francisco",
"country": "USA"
}
}
}Example Queries
| Query | Result |
|---|---|
$.store.name | "TechMart" |
$.store.products[*].name | ["Laptop", "Mouse", "Keyboard", "Monitor"] |
$..price | [999, 29, 79, 299] |
$.store.products[0] | {"id": 1, "name": "Laptop", ...} |
$.store.products[-1].name | "Monitor" |
$.store.products[0:2].name | ["Laptop", "Mouse"] |
$.store.products[?(@.price<100)].name | ["Mouse", "Keyboard"] |
$.store.products[?(@.inStock==true)].name | ["Laptop", "Mouse", "Monitor"] |
$..city | ["San Francisco"] |
Filter Expressions
Filters ([?()]) let you select elements that match a condition. Use @ to reference the current element:
[?(@.price > 100)]— Price greater than 100[?(@.price <= 50)]— Price 50 or less[?(@.inStock == true)]— In stock items[?(@.name)]— Has a name property[?(@.tags[*] == "sale")]— Has "sale" in tags array
Real-World Use Cases
Extract All Emails from API Response
$..emailFinds every email field anywhere in the document—useful when you don't know the exact structure.
Get Failed Items from a Batch Response
$.results[?(@.status == "failed")]Filters to only the items that failed processing.
Find Products in a Price Range
$.products[?(@.price >= 10 && @.price <= 50)]Combines multiple conditions with &&.
Get Specific Fields from Nested Arrays
$.orders[*].items[*].skuExtracts SKUs from all items in all orders.
Pro Tips
- 💡 Start with
$and build up — Test$.storebefore trying$.store.products[?(@.price>100)].name - 💡 Use
..when you're not sure of the path —$..idfinds all IDs regardless of nesting depth - 💡 Filter returns an array — Even if one item matches, you get
[item]notitem - 💡 Dot notation vs bracket notation —
$.store.nameequals$['store']['name']. Use brackets for special characters:$['my-field']
JSONPath vs Alternatives
| Tool | Best For |
|---|---|
| JSONPath | Quick extraction, language-agnostic, browser-friendly |
| jq | Command-line processing, complex transformations |
| JavaScript | When you need full programming logic |
Related Tools
- JSON Validator — Validate and format JSON
- JSON Diff — Compare two JSON documents
- JSON Schema Validator — Validate against a schema
Common Mistakes & Pro Tips
- Dot vs bracket notation — $.store.book and $['store']['book'] are equivalent. Use bracket notation with quotes when a key contains spaces, dots, or special characters, for example $['user.name'] or $['first name'], since dot notation would misparse those. The root is always $.
- Wildcards and array indices — Use [*] to select all elements or members at a level, and numeric indices like [0] for a specific element. Many implementations support slices such as [0:2] and negative indices like [-1] for the last item. Combine them: $.store.book[*].author selects every author.
- Recursive descent with .. — The .. operator searches all levels, so $..author finds every author key anywhere in the document regardless of depth. It is powerful but broad; it can match in unexpected branches, so scope it (for example $.store..price) when you only want part of the tree.
- Filter expressions use @ — Filters like [?(@.price < 10)] keep elements where the predicate holds, with @ referring to the current element. You can test existence ([?(@.isbn)]) and combine conditions with && and ||. Quote string comparisons carefully, e.g. [?(@.category == 'fiction')].
- Implementations differ — JSONPath was never a single formal standard until RFC 9535, so older libraries differ on slices, filter syntax, regex matches, and whether results are values or paths. If an expression behaves unexpectedly, it may be an implementation quirk rather than a mistake in your query.
Frequently Asked Questions
What's the difference between dot and bracket notation?
They select the same thing for simple keys, so $.store.book equals $['store']['book']. Bracket notation is required when a key contains characters that break dot syntax, such as spaces, dots, or hyphens, for example $['order.id']. Array elements always use brackets with an index, like [0].
How do I filter an array by a condition?
Use a filter expression where @ is the current element: $.store.book[?(@.price < 10)] returns books cheaper than 10. You can test for a property's existence with [?(@.isbn)] and combine predicates using && and ||. Wrap string literals in quotes, as in [?(@.category == 'fiction')].
How do I find a key no matter how deeply it's nested?
Use recursive descent: $..author returns every "author" value anywhere in the document. To limit the search to a subtree, anchor it first, for example $.store..price only descends within store. Because .. matches at all depths, double-check results when your document reuses key names in different sections.
How do I get the last element of an array?
Most implementations support negative indices, so $.store.book[-1] returns the last book. Slices also work: [0:2] takes the first two elements and [-2:] the last two. If negative indexing is not supported by a given library, you may need to know the array length and use an explicit index.
Why does my JSONPath return different results elsewhere?
JSONPath behavior historically varied between libraries because there was no single specification until RFC 9535 in 2024. Differences show up in slice handling, filter syntax, regular-expression matching, and whether the query returns matched values or their paths. When in doubt, test the exact expression in the tool you will actually run it in.
Does a query select values or their locations?
Standard JSONPath evaluation returns the matched values from your document. Some tools can also report the path to each match, which is useful for knowing where a value lives. Check the output mode here, since selecting all authors with $..author yields a list of author values, not the objects containing them.
Is my JSON processed locally?
Yes. The JSONPath query runs against your document entirely in the browser, with no upload. That means you can query sensitive API responses or config files without them leaving your machine.