A JSONPath cheat sheet for real queries
Most day-to-day querying uses a small set of operators. Keep this table handy:
| Expression | Returns |
|---|---|
$.store.book[0].title | First book’s title |
$.store.book[*].author | Every book’s author |
$..author | All author values, any depth |
$.store.book[-1] | Last book |
$.store.book[0:2] | First two books (end-exclusive) |
$.store.book[?(@.price < 10)] | Books cheaper than 10 |
$..* | Every value in the document |
The $ is always the root, @ refers to the current element inside a filter, and .. scans recursively at every depth.
The two operators that cause the most confusion
Recursive descent (..) is powerful but blunt — $..author finds every author anywhere in the tree, which is exactly what you want until it returns far more than expected on a large document. Narrow it with a specific key, and prefer an explicit path ($.store.book[*].author) when you know the structure.
Filters (?()) trip people on syntax: the current element must be @ (not $), string comparisons need quotes (?(@.name == 'Jane')), and the operator is == not ===. Get those three right and filters become the most useful tool in the set.
JSONPath, JMESPath, or jq?
They solve overlapping problems with different trade-offs:
- JSONPath — XPath-style, great for selecting values from API responses; now RFC 9535.
- JMESPath — also query-focused, with a more consistent spec; used by AWS CLI’s
--query. - jq — a full command-line language that can transform, reshape, and compute, not just select. Steeper to learn, far more powerful for editing.
If you only need to find values, JSONPath is the simplest. If you need to reshape JSON, that’s jq territory.
Debugging a query that returns nothing
An empty result almost always means a path mismatch, and the usual suspects are: case sensitivity ($.User ≠ $.user), a missing array index (a value inside an array needs [0] or [*]), or the wrong nesting level. Start broad with $.* to list the top-level keys, then walk down level by level. Everything runs locally in your browser, so you can iterate on sensitive API responses without anything leaving your device.