If you have ever needed to extract a specific value from a deeply nested API response, JSONPath is the tool for that job. It is to JSON what XPath is to XML — a path query language that lets you select one or many values from a JSON document with a single expression.
JSONPath was originally defined by Stefan Goessner in 2007, and was officially standardised in RFC 9535 (published February 2024). It is used in AWS IAM policies, Kubernetes admission webhooks, Grafana alerting, and dozens of API testing frameworks.
Test JSONPath expressions in your browser:
Open JSONPath Tester →The root element: $
Every JSONPath expression starts with $, which represents the root of the document. Given this JSON:
{
"store": {
"book": [
{ "author": "Nigel Rees", "price": 8.95 },
{ "author": "Evelyn Waugh", "price": 12.99 }
],
"bicycle": { "color": "red", "price": 19.95 }
}
}
The expression $ returns the entire document. Everything else is a path from there.
Dot and bracket notation
You can navigate child keys using dot notation (.key) or bracket notation (['key']). Both are equivalent for simple key names:
| Expression | Result |
|---|---|
$.store.bicycle.color | ["red"] |
$.store['bicycle']['color'] | ["red"] |
$.store.book[0].author | ["Nigel Rees"] |
$.store.book[1].price | [12.99] |
Use bracket notation when a key contains spaces, hyphens, or starts with a digit: $['my-key'].
Wildcard: [*]
The wildcard * matches all elements of an array or all values of an object:
| Expression | Result |
|---|---|
$.store.book[*].author | All authors: ["Nigel Rees","Evelyn Waugh"] |
$.store.* | All values under store (the book array + bicycle object) |
$.store.book[*] | All book objects |
Recursive descent: ..
The double-dot operator searches all descendants, regardless of depth:
| Expression | Result |
|---|---|
$..author | All author fields anywhere in the document |
$..price | All prices (books + bicycle): [8.95, 12.99, 19.95] |
$..book[0] | First book in any nested book array |
Recursive descent is the JSONPath equivalent of // in XPath. It is powerful but can be slow on very large documents.
Array slices
JSONPath supports Python-style array slicing: [start:end:step].
| Expression | Result |
|---|---|
$.store.book[0] | First element (index 0) |
$.store.book[-1] | Last element (JSONPath Plus extension) |
$.store.book[0:2] | Elements at index 0 and 1 |
$.store.book[0,1] | Elements at index 0 and 1 (union) |
$.store.book[::2] | Every second element |
Filter expressions: [?()]
Filter expressions let you select elements that satisfy a condition. The current element is referenced with @:
| Expression | Meaning |
|---|---|
$.store.book[?(@.price < 10)] | Books cheaper than $10 |
$.store.book[?(@.author == "Evelyn Waugh")] | Book by a specific author |
$.store.book[?(@.price)] | Books that have a price field |
$..book[?(@.price > $.store.bicycle.price)] | Books more expensive than the bicycle |
Supported comparison operators: ==, !=, <, <=, >, >=. You can combine conditions with && and ||.
JSONPath cheat sheet
| Syntax | Description |
|---|---|
$ | Root element |
.key or ['key'] | Child key |
[n] | Array index (zero-based) |
[*] | All elements |
[a,b] | Union of indices or keys |
[a:b] | Array slice |
.. | Recursive descent |
[?(@.x)] | Filter — elements where x exists |
[?(@.x == y)] | Filter — elements where x equals y |
JSONPath in practice
AWS IAM condition keys
AWS uses JSONPath-like syntax in IAM condition keys and CloudFormation. Understanding path syntax makes reading policies much easier.
Kubernetes admission webhooks
Kubernetes uses JSONPath in kubectl output templates:
kubectl get pods -o jsonpath='{.items[*].metadata.name}'
Grafana alerting
Grafana alert conditions use JSONPath to extract values from API datasources. A path like $.data.result[0].value[1] extracts the metric value from a Prometheus response.
API testing (Postman, Bruno)
Most API testing tools support JSONPath for assertions: pm.expect(jsonData.store.book[0].price).to.equal(8.95).
Frequently Asked Questions
Why does JSONPath always return an array?
JSONPath is designed to return a set of matching nodes, so the result is always wrapped in an array even when only one value matches. This is consistent with how XPath works. If you need the scalar value, read the first element of the result array.
What is the difference between JSONPath and JMESPath?
JMESPath is a competing query language used in AWS CLI. JSONPath uses a path syntax similar to XPath ($.store.book[*].author). JMESPath uses a different syntax (store.book[*].author) and includes built-in functions. JSONPath is more widely used in non-AWS contexts; JMESPath is the default in AWS CLI and Boto3.
Is JSONPath the same as RFC 9535?
RFC 9535 (published February 2024) is the first formal IETF standard for JSONPath. It largely codifies the original Goessner specification with clarifications and a formal grammar. Most existing JSONPath implementations are compatible with RFC 9535, though some extended features (like JSONPath Plus's parent selector) are not part of the standard.
Does JSONPath support regular expressions in filters?
RFC 9535 defines a match() function for regex matching in filter expressions. JSONPath Plus supports this as @=~ /pattern/ or via the @.key.match(regex) syntax. Support varies by implementation.
Ready to test your JSONPath expressions?
Open JSONPath Tester →