Complete JSONPath Syntax & Query Reference Guide
JSONPath is the universal query expression language for extracting, filtering, and projecting data from JSON (JavaScript Object Notation) documents. Standardized by the IETF under RFC 9535, JSONPath provides deterministic path addressing across programming ecosystems including JavaScript/TypeScript, Python, Java, Go, Rust, and C#.
Whether you are querying large REST API responses, configuring Kubernetes kubectl output templates, defining AWS Step Functions payload filters, or asserting integration test expectations, mastering JSONPath syntax allows you to extract precise data points without writing bespoke traversal logic.
JSONPath Syntax Operators (RFC 9535 Standard)
| Operator | Name | Description | Expression Example |
|---|---|---|---|
| $ | Root Object | The root object or array of the JSON document. All JSONPath expressions begin with this selector. | $ |
| @ | Current Node | Refers to the current element being processed in a filter predicate condition. | @.price > 10 |
| .name or ['name'] | Child Property | Accesses an immediate child property by name. Bracket notation is mandatory for keys with special characters. | $.user.address['zip-code'] |
| .. | Recursive Descent | Recursively traverses all child and nested descendant levels to find matching property names or items. | $..author |
| * | Wildcard Selector | Matches all property values in an object, or all element items in an array. | $.store.books[*] |
| [n] or [-n] | Array Index | Selects a specific array item by 0-based index. Negative indices count backward from the end of the array. | $.items[0] / $.items[-1] |
| [start:end:step] | Array Slice | Extracts a subset slice of array elements using Python-style slice semantics (start inclusive, end exclusive). | $.items[0:5] / $.items[::2] |
| ['k1','k2'] or [0,2] | Union Operator | Selects multiple explicit keys or multiple array indices simultaneously into a single result set. | $.user['name','email'] |
| [?(expr)] | Filter Predicate | Filters array items by applying a boolean expression containing comparison (<, <=, ==, !=, >=, >) or logical (&&, ||) operators. | $[?(@.active && @.age >= 18)] |
Real-World API Querying & Filtering Examples
Consider the following realistic e-commerce API payload containing nested stores, orders, products, and customer records:
{
"store": {
"name": "Cloud Warehouse #4",
"location": { "city": "San Francisco", "state": "CA" },
"inventory": [
{ "id": "p-101", "category": "electronics", "title": "Wireless Keyboard", "price": 49.99, "stock": 140, "featured": true },
{ "id": "p-102", "category": "electronics", "title": "USB-C Hub", "price": 29.50, "stock": 0, "featured": false },
{ "id": "p-103", "category": "office", "title": "Ergonomic Chair", "price": 249.00, "stock": 18, "featured": true },
{ "id": "p-104", "category": "books", "title": "Designing Data-Intensive Applications", "price": 38.20, "stock": 52, "featured": false }
],
"orders": [
{ "orderId": "ord-881", "customerId": "c-44", "total": 99.98, "status": "shipped", "items": ["p-101", "p-101"] },
{ "orderId": "ord-882", "customerId": "c-91", "total": 249.00, "status": "pending", "items": ["p-103"] }
]
}
} Expression:
$.store.inventory[*].title
Extracts a flat list of strings: ["Wireless Keyboard", "USB-C Hub", "Ergonomic Chair", "Designing Data-Intensive Applications"].
Expression:
$.store.inventory[?(@.category == 'electronics' && @.stock > 0)] Returns only products in the electronics category where available stock is strictly greater than 0.
Expression:
$..id
Recursively scans all object levels in the tree and returns every value bound to the key "id".
Expression:
$.store.inventory[-2:]
Returns the tail slice of the inventory array (the last 2 items) without needing to query the array length beforehand.
Architectural Comparison: JSONPath vs. jq vs. XPath
Selecting the right query tool depends on your runtime execution environment, data format, and transformation requirements:
| Feature / Dimension | JSONPath (RFC 9535) | jq (CLI Engine) | XPath (W3C Standard) |
|---|---|---|---|
| Target Data Format | JSON / JSONC | JSON / JSON Streams (ndjson) | XML / HTML DOM |
| Primary Purpose | Querying, key extraction, filtering | Full data transformation, reshaping, pipelines | Document navigation, schema validation |
| Language Paradigm | Declarative path expressions | Turing-complete functional filter pipeline | Declarative tree path traversal |
| Ecosystem Integration | Native in Spring, Kubernetes, AWS, Postman | CLI binaries, shell scripts, CI/CD runners | Java DOM, .NET XML, XSLT engines |
| Structural Reshaping | Read-only selection & extraction | Constructs new JSON objects & arrays | Read-only node selection |
| Browser & Web Worker | Ultra-lightweight (< 15KB pure JS) | Requires heavy WebAssembly (Wasm) binary | Native DOMParser / XPathEvaluator |
Common JSONPath Pitfalls & Troubleshooting
Dot notation breaks on property keys that contain hyphens, spaces, colons, or periods (such as "user-id" or "k8s.io/namespace"). Always wrap these keys in bracket quotes: $['k8s.io/namespace'] or $.user['user-id'].
While RFC 9535 supports both single and double quotes for string literals within filter predicates, standardizing on single quotes inside filter brackets ([?(@.status == 'active')]) avoids escaping clashes when embedding JSONPath inside shell commands or JSON configuration strings.
In standard JSONPath, requesting an index that does not exist (such as $.items[99] on a 3-item array) gracefully returns an empty result set rather than throwing an exception. In your application code, always verify that returned matches have length before dereferencing array indices.