JSON (JavaScript Object Notation) is everywhere—from APIs to logs—but navigating deeply nested structures can be tedious. That’s where JSONPath (a JSON path query language) comes in, letting you extract data effortlessly—much like XPath does for XML. This guide takes you on a journey: learn the syntax, see real-world patterns, and discover tools (like PostPilot) to query JSON interactively.
JSONPath is a query language for JSON structures, letting you fetch values without writing explicit loops. Powered by RFC 9535, it supports:
?()
) using @
and comparison operatorslength()
, count()
, match()
, search()
, and value()
Here’s a simple example using JavaScript:
import jp from 'jsonpath';
const jsonData = {
"store": {
"book": [
{
"category": "fiction",
"title": "The Catcher in the Rye",
"price": 10.99,
"authors": ["J.D. Salinger"]
},
{
"category": "fiction",
"title": "To Kill a Mockingbird",
"price": 8.99,
"authors": ["Harper Lee"]
},
{
"category": "non-fiction",
"title": "Sapiens",
"price": 14.99,
"authors": ["Yuval Noah Harari", "Others"],
"isbn": "0-395-19395-8"
}
],
"bicycle": {
"color": "red",
"price": 199.99
},
"voucherPrice": 10
},
"history": {
"add.book": "2025-01-01",
"remove.book": "2025-01-02"
}
};
const titles = jp.query(jsonData, '$.store.book[*].title');
console.log(titles);
// ["The Catcher in the Rye", "To Kill a Mockingbird", "Sapiens"]
Dive into the styles of json path query syntax:
Expression | Description | Example |
---|---|---|
$ | Root selector | $.store , $ |
.name / ['name'] | Child (member) access | $.store.book , $['history']['add.book'] |
* , [*] , .* | Wildcard selector: all children/elements | $.store.* , $.store.book[*].title |
.. , ..name , ..* | Recursive descent: all descendants | $..price , ..name , ..* |
[n] | Array index (supports negative) | $.store.book[0] , $.store.book[-1] |
[start:end:step] | Slicing with optional step | [0:2:1] , [:2] , [-3:] |
[i,j,...] | Union: multiple indexes or properties | ['a','b'] , $..book[0,1] |
?(<filter>) | Filters with boolean expressions | $..book[?(@.price > 10)] |
@ | Current node inside filters | ?(@.category=='fiction') |
func() | Function extensions | $[?length(@.authors) >= 2] |
Start with practical, everyday queries using JSONPath:
Query: $.store.book[*].title
Result: ["The Catcher in the Rye", "To Kill a Mockingbird", "Sapiens"]
Query: $.store.book[?(@.price > 10)].title
Result: ["The Catcher in the Rye", "Sapiens"]
Query: $.store.bicycle.price
Result: 199.99
Query: $.store..price
Result: [10.99, 8.99, 14.99, 199.99]
Query: $..book[-1]
Result: [
{
"category": "fiction",
"title": "To Kill a Mockingbird",
"price": 8.99,
"authors": [ "Harper Lee" ]
}
]
Returns the last book object in the list.
Query: $..book[:2]
Result: [
{
"category": "fiction",
"title": "The Catcher in the Rye",
"price": 10.99,
"authors": [ "J.D. Salinger" ]
},
{
"category": "fiction",
"title": "To Kill a Mockingbird",
"price": 8.99,
"authors": [ "Harper Lee" ]
}
]
Returns the first two book entries.
Query: $..book[?(@.isbn)]
Result: [
{
"category": "non-fiction",
"title": "Sapiens",
"price": 14.99,
"authors": [ "Yuval Noah Harari", "Others" ],
"isbn": "0-395-19395-8"
}
]
Filters books containing an isbn
property.
Here’s where JSONPath shines—filters, functions, and regex:
Query: $[?length(@.authors) >= 5]
Result: [ /* objects with authors array of at least 5 entries */ ]
The length()
function applies to object (number of keys), array (number of elements), string (number of characters).
match()
Query: $.products[?match(@.sku, '^[A-Z]{3}\\d{4}$')]
Result: [ /* products where sku looks like ABC1234 */ ]
Use match()
for full-string regex checks.
search()
Query: $.comments[?search(@.text, 'urgent')]
Result: [ /* comments containing "urgent" */ ]
Use search()
to find texts containing a specific substring.
count()
(advanced)Query: $.store.book[?count(@['category','title','price','isbn']) == 4]
Result: [ /* books with exactly 4 properties listed */ ]
Use count()
to evaluate the number of matched fields. count
accepts node lists as parameter (possibly taken from a filter-query), while length
accepts "direct" JSON value as parameter.
value()
(advanced)Query: $[?value(@..color) == "red"]
Result: [ /* store object */ ]
Returns the "store" object where a single-node list evaluates to the scalar value 'red'
. Multi-node or empty lists return Nothing
.
Query: $..articles[
?(
length(@.authors) >= 2 &&
count(@.tags) > 3 &&
match(@.title, '^JSONPath') &&
search(@.content, '\\bguide\\b')
)
]
Result: [ /* filtered articles */ ]
Selects articles that:
Function | Description |
---|---|
length(<value>) | Returns length of an array, object, or string |
count(<nodelist>) | Returns the number of matched nodes |
match(text, iregexp) | Returns true if the entire text matches the regex (anchored) |
search(text, iregexp) | Returns true if text contains a match (non-anchored) |
value(<nodelist>) | Converts a single-node list into its raw value; else returns null |
Together, these enable highly expressive and efficient JSON path queries covering conditional logic, slicing, filtering, and transformation.
To use JSONPath in JavaScript, install the jsonpath
library:
npm install jsonpath
Example (ESM syntax):
import { query, paths } from 'jsonpath';
const authors = query(doc, '$.store.book[*].authors');
// [
// [ "J.D. Salinger" ],
// [ "Harper Lee" ],
// [ "Yuval Noah Harari", "Others" ]
// ]
const allPaths = paths(doc, '$.store.book[*].authors');
// [
// ["$","store","book",0,"authors"],
// ["$","store","book",1,"authors"],
// ["$","store","book",2,"authors"]
// ]
com.jayway.jsonpath
Json.NET
, JsonPath.Net
jsonpath-ng
, jsonpath-python
Flow JSONPath
jsonpath
GJson
Want a UI to test multiple JSONPath expressions? Try PostPilot.dev:
By mastering json path query syntax—selectors, filters, and functions—you’ll unlock fast, expressive JSON querying from simple lookups to deep analytics. Tools like PostPilot.dev make exploration easier, while RFC‑compliant libraries across languages keep your code maintainable.
Start crafting queries that are concise, powerful, and flexible. Happy JSON parsing!