JSONPath is a query language for JSON, similar to how XPath works for XML. It lets you extract specific pieces of data from complex JSON structures using path expressions. Instead of writing loops to navigate nested objects, you write a single query string.
Sample JSON for Examples
We'll use this JSON throughout the tutorial:
{
"store": {
"name": "Tech Haven",
"books": [
{ "title": "1984", "author": "Orwell", "price": 9.99, "inStock": true },
{ "title": "Dune", "author": "Herbert", "price": 12.99, "inStock": true },
{ "title": "Foundation", "author": "Asimov", "price": 8.99, "inStock": false }
],
"electronics": [
{ "name": "Laptop", "price": 999, "brand": "TechCo" },
{ "name": "Phone", "price": 699, "brand": "MobileCorp" }
]
}
}
Basic Syntax
JSONPath expressions always start with $ representing the root object:
| Expression | Meaning |
$ | The root object |
$.key | Child property "key" |
$['key'] | Child property (bracket notation) |
$.array[0] | First element of array |
$.array[-1] | Last element of array |
$.* | All children (wildcard) |
$.. | Recursive descent (any depth) |
Dot Notation vs Bracket Notation
Both notations access properties, but bracket notation handles special characters:
// Dot notation (cleaner for simple keys)
$.store.name โ "Tech Haven"
$.store.books โ [array of books]
// Bracket notation (required for special chars)
$['store']['name'] โ "Tech Haven"
$['my-key'] โ (handles hyphens)
$['key with spaces'] โ (handles spaces)
Array Access
// Single index
$.store.books[0] โ { "title": "1984", ... }
$.store.books[1].title โ "Dune"
// Negative index (from end)
$.store.books[-1] โ { "title": "Foundation", ... }
// Multiple indices
$.store.books[0,2] โ [first and third books]
// Slice notation [start:end:step]
$.store.books[0:2] โ [first two books]
$.store.books[1:] โ [all except first]
$.store.books[::2] โ [every other book]
Wildcards
The * wildcard matches all elements at the current level:
// All items in array
$.store.books[*] โ [all books]
// Specific field from all items
$.store.books[*].title โ ["1984", "Dune", "Foundation"]
$.store.books[*].price โ [9.99, 12.99, 8.99]
// All properties of an object
$.store.* โ [books array, electronics array, "Tech Haven"]
Recursive Descent (..)
The .. operator searches recursively through all nested levels:
// Find all "price" values anywhere
$..price โ [9.99, 12.99, 8.99, 999, 699]
// Find all "title" values anywhere
$..title โ ["1984", "Dune", "Foundation"]
// All arrays anywhere
$..[*] โ [every element in every array]
// All objects with a "price" property
$..[?(@.price)] โ [all books and electronics]
Filters (?())
Filters let you select elements that match a condition. Use @ to reference the current element:
// Books under $10
$.store.books[?(@.price < 10)]
โ [{ "title": "1984", ... }, { "title": "Foundation", ... }]
// Books in stock
$.store.books[?(@.inStock == true)]
โ [{ "title": "1984", ... }, { "title": "Dune", ... }]
// Books by specific author
$.store.books[?(@.author == 'Orwell')]
โ [{ "title": "1984", ... }]
// Expensive electronics (over $700)
$.store.electronics[?(@.price > 700)]
โ [{ "name": "Laptop", ... }]
Filter Operators
| Operator | Description | Example |
== | Equals | @.status == 'active' |
!= | Not equals | @.type != 'admin' |
< | Less than | @.price < 100 |
<= | Less or equal | @.age <= 30 |
> | Greater than | @.score > 90 |
>= | Greater or equal | @.qty >= 1 |
=~ | Regex match | @.name =~ /^A.*/ |
in | In list | @.color in ['red','blue'] |
&& | AND | @.price < 10 && @.inStock |
|| | OR | @.type == 'A' || @.type == 'B' |
Complex Filter Examples
// Cheap books that are in stock
$.store.books[?(@.price < 10 && @.inStock == true)]
// Books with title containing "D" (regex)
$.store.books[?(@.title =~ /D/)]
// Items where property exists
$.store.books[?(@.isbn)] // books with ISBN field
// Nested property check
$.orders[?(@.customer.vip == true)]
JSONPath vs JavaScript
Here's how JSONPath queries compare to equivalent JavaScript code:
// Get all book titles
// JSONPath:
$.store.books[*].title
// JavaScript:
data.store.books.map(book => book.title)
// Get books under $10
// JSONPath:
$.store.books[?(@.price < 10)]
// JavaScript:
data.store.books.filter(book => book.price < 10)
// Find all prices anywhere
// JSONPath:
$..price
// JavaScript:
function findPrices(obj) {
let results = [];
for (let key in obj) {
if (key === 'price') results.push(obj[key]);
if (typeof obj[key] === 'object') {
results = results.concat(findPrices(obj[key]));
}
}
return results;
}
findPrices(data)
As you can see, JSONPath is much more concise for deep queries!
Using JSONPath in Code
// JavaScript (jsonpath-plus library)
const { JSONPath } = require('jsonpath-plus');
const result = JSONPath({ path: '$.store.books[*].title', json: data });
// ["1984", "Dune", "Foundation"]
# Python (jsonpath-ng library)
from jsonpath_ng import jsonpath, parse
expr = parse('$.store.books[*].title')
matches = [m.value for m in expr.find(data)]
# ["1984", "Dune", "Foundation"]
// Java (Jayway JsonPath)
List<String> titles = JsonPath.read(json, "$.store.books[*].title");
// PHP (JSONPath library)
$titles = (new JSONPath($data))->find('$.store.books[*].title');
Real-World Use Cases
- API Response Parsing โ Extract specific fields from complex API responses
- Configuration Files โ Query settings from nested config structures
- Log Analysis โ Find specific entries in JSON log files
- Data Transformation โ Select data for ETL pipelines
- Testing โ Assert specific values in API test responses
- REST APIs โ Some APIs support JSONPath for field selection
JSONPath Cheat Sheet
| Expression | Description |
$ | Root object |
@ | Current object (in filters) |
.key or ['key'] | Child operator |
.. | Recursive descent |
* | Wildcard (all elements) |
[n] | Array index |
[start:end] | Array slice |
[?(expr)] | Filter expression |
[a,b,c] | Multiple indices |
Try It Yourself
Ready to practice? Use our free JSONPath Query Tool to test expressions against your own JSON data. Paste JSON, write queries, and see results instantly โ great for learning and debugging.
For exploring JSON structure visually, try our JSON Tree Viewer to understand the paths before writing queries.