JSONPath Query Guide: Filter & Extract Data from JSON
JSONPath is to JSON what XPath is to XML - a query language for navigating and extracting values from complex nested structures. This guide covers the full syntax, real examples, and how to use it in JavaScript, Python, and the command line.
The Problem: Drilling Into Nested JSON
You have a deep JSON response from an API. You need to extract a specific field from every item in a nested array, or filter objects by a condition. In JavaScript you can chain bracket notation, but it gets verbose fast and breaks on missing intermediate keys. JSONPath solves this with a concise, XPath-inspired query syntax.
Consider this bookstore JSON (the canonical JSONPath example):
{
"store": {
"book": [
{ "title": "Sayings of the Century", "author": "Nigel Rees", "price": 8.95, "category": "reference" },
{ "title": "Sword of Honour", "author": "Evelyn Waugh", "price": 12.99, "category": "fiction" },
{ "title": "Moby Dick", "author": "Herman Melville","price": 8.99, "category": "fiction","isbn": "0-553-21311-3" },
{ "title": "The Lord of the Rings", "author": "Tolkien", "price": 22.99, "category": "fiction","isbn": "0-395-19395-8" }
],
"bicycle": { "color": "red", "price": 19.95 }
}
}
JSONPath Syntax Reference
| Expression | Meaning |
|---|---|
$ | Root element / document root |
.key | Child key (dot notation) |
['key'] | Child key (bracket notation, supports special chars) |
.. | Recursive descent - searches all descendants |
* | Wildcard - all children |
[n] | Array element at index n (0-based) |
[-1] | Last element of an array |
[0:3] | Array slice: elements 0, 1, 2 |
[0,2] | Union: elements at index 0 and 2 |
[?(@.price < 10)] | Filter: items where price < 10 |
@ | The current node (used inside filter expressions) |
Real Examples Against the Bookstore JSON
Get All Book Titles
$.store.book[*].title
// ["Sayings of the Century", "Sword of Honour", "Moby Dick", "The Lord of the Rings"]
Get the First Book
$.store.book[0]
// { "title": "Sayings of the Century", "author": "Nigel Rees", "price": 8.95, ... }
Get the Last Book
$.store.book[-1]
// { "title": "The Lord of the Rings", ... }
Get the First Three Books
$.store.book[0:3]
// First 3 books (indices 0, 1, 2)
Get All Prices (Recursive)
$..price
// [8.95, 12.99, 8.99, 22.99, 19.95] - books + bicycle price
Filter: Books Under $10
$.store.book[?(@.price < 10)]
// Sayings of the Century (8.95) and Moby Dick (8.99)
Filter: Books With an ISBN Field
$.store.book[?(@.isbn)]
// Moby Dick and The Lord of the Rings - only books that have the isbn key
Filter: Fiction Books Over $10
$.store.book[?(@.category == "fiction" && @.price > 10)]
// Sword of Honour (12.99) and The Lord of the Rings (22.99)
Format JSON Before Querying
Hard to write JSONPath expressions against minified JSON? Paste it into our formatter first to get a clear view of the structure. Free, instant, in-browser.
Open JSON Formatter →Step-by-Step: Writing Your First JSONPath Query
- Start at the root. Every JSONPath expression begins with
$, which represents the root of the document. - Navigate to the target. Use dot notation for keys:
$.store.book. Use bracket notation for keys with special characters:$['some-key']. - Add array access if needed.
[0]for first element,[*]for all elements,[-1]for last. - Add a filter expression for conditions.
[?(@.field operator value)]. Supported operators:== != < > <= >=and&&/||for compound conditions. - Use
..for recursive search. If you do not know the exact nesting level,..searches all descendants. - Test with a tool. Use our JSON Formatter to paste and inspect your structure before writing queries.
Using JSONPath in JavaScript
Browsers and Node.js do not have native JSONPath support (unlike XPath for XML). Use the jsonpath-plus library:
import { JSONPath } from 'jsonpath-plus';
const result = JSONPath({ path: '$.store.book[?(@.price < 10)].title', json: data });
// ['Sayings of the Century', 'Moby Dick']
// Get paths in addition to values
const withPaths = JSONPath({ path: '$..price', json: data, resultType: 'all' });
// Returns { path, value, parent, parentProperty } for each match
The jsonpath package is another popular option but less actively maintained. jsonpath-plus implements more of the specification including negative indices and extended filter functions.
Using JSONPath in Python
from jsonpath_ng import parse
# Install: pip install jsonpath-ng
expr = parse('$.store.book[?(@.price < 10)].title')
matches = [match.value for match in expr.find(data)]
# ['Sayings of the Century', 'Moby Dick']
# Recursive
expr2 = parse('$..price')
prices = [m.value for m in expr2.find(data)]
# [8.95, 12.99, 8.99, 22.99, 19.95]
JSONPath with jq (Command Line)
jq is the gold standard for JSON processing on the command line. Its syntax differs from standard JSONPath but is more powerful:
# All book titles
jq '.store.book[].title' data.json
# Books under $10
jq '.store.book[] | select(.price < 10)' data.json
# Just the titles of cheap books
jq '[.store.book[] | select(.price < 10) | .title]' data.json
# All prices everywhere (recursive equivalent)
jq '.. | .price? // empty' data.json
# Count books in each category
jq '.store.book | group_by(.category) | map({(.[0].category): length}) | add' data.json
JSONPath in CI/CD and Config
JSONPath is widely used beyond ad-hoc querying:
- Kubernetes:
kubectl get pods -o jsonpath='{.items[*].metadata.name}'- extract pod names from the API response - AWS CLI:
aws ec2 describe-instances --query 'Reservations[*].Instances[*].PublicIpAddress'uses JMESPath (a JSON query language similar to JSONPath) - GitHub Actions:
fromJSON(steps.output.outputs.json).field - Postman tests:
pm.response.json().data[0].id - JSON Schema:
$refpointers use JSON Pointer syntax (RFC 6901), which is different from JSONPath but related
JSONPath vs JMESPath vs jq
- JSONPath - Original spec by Stefan Goessner (2007). Widely supported but has implementation variations. Best for: general purpose querying.
- JMESPath - Used by AWS CLI and some cloud tooling. More rigorously specified. Best for: AWS and consistent cross-platform use.
- jq - Command-line tool with its own query language. Most powerful, supports transformations not just queries. Best for: shell scripts and data transformation pipelines.
If you are working with Kubernetes, learn the
kubectlJSONPath dialect. If you are working with AWS, learn JMESPath. For everything else, standard JSONPath with jsonpath-plus (JS) or jsonpath-ng (Python) covers 95% of use cases.
Frequently Asked Questions
Does JSONPath work on all JSON, or only arrays?
JSONPath works on any valid JSON document - objects, arrays, nested combinations. The root $ can be an object or an array. Array-specific syntax like [0] and [?()] only applies when you navigate into an array element.
What is the difference between $.store.book and $..book?
$.store.book navigates the exact path: root → store → book. $..book uses recursive descent and finds any key named book anywhere in the document, at any nesting level. The recursive version is slower but useful when you do not know the exact structure.
Can I use JSONPath to modify values, not just read them?
Standard JSONPath is read-only. For modifications, use your language's native object manipulation after querying, or use jq which supports transforms: jq '.store.book[].price *= 1.1' data.json increases all book prices by 10%.
Why do some JSONPath implementations return different results?
The original JSONPath specification (2007) left some behavior undefined. Different libraries handle edge cases differently - particularly negative indices, recursive descent on arrays, and filter operator support. The IETF standardized JSONPath in RFC 9535 (2024), which should improve interoperability going forward.
How do I query a key that contains special characters like dots or spaces?
Use bracket notation: $['some.key.with.dots'] or $['key with spaces']. Dot notation ($.some.key) parses each dot as a path separator, so it breaks with dots in key names.
Format and explore your JSON structure before writing queries → Open our free JSON Formatter.
Usman has 10+ years of experience securing enterprise infrastructure, managing high-traffic servers, and building zero-knowledge security tools. Read more about the author.