JSONPath Expressions - Query JSON Like a Pro
Master JSONPath expressions to query and extract data from JSON documents efficiently. Learn syntax, operators, and practical examples.
What is JSONPath?
JSONPath is a query language for JSON, similar to how XPath is used for XML. It provides a simple way to navigate through complex JSON structures and extract specific data without writing complex parsing logic.
Why Use JSONPath?
- Extract specific data from large JSON responses
- Test API responses for expected values
- Transform data by selecting specific fields
- Navigate complex nested structures easily
- Query arrays with filtering capabilities
Basic Syntax
JSONPath expressions always start with $ representing the root element.
{
"store": {
"book": [
{
"title": "JavaScript Guide",
"price": 29.99
},
{
"title": "Python Basics",
"price": 34.99
}
]
}
}
Basic Operators
| Operator | Description | Example |
|---|---|---|
$ |
Root element | $ |
. |
Child operator | $.store.book |
[] |
Subscript operator | $[0] |
* |
Wildcard | $.store.* |
.. |
Recursive descent | $..price |
@ |
Current element (in filters) | $..book[?(@.price < 30)] |
Accessing Data
Accessing Objects
Dot notation:
$.store.book
// Returns: entire book array
Bracket notation:
$['store']['book']
// Returns: same as above
Accessing Arrays
By index:
$.store.book[0]
// Returns: first book
Multiple indices:
$.store.book[0,1]
// Returns: first two books
Array slicing:
$.store.book[0:2] // First two books
$.store.book[-1] // Last book
$.store.book[1:] // All books from index 1
$.store.book[:2] // First two books
Wildcard Selection
All children:
$.store.book[*]
// Returns: all books
$.store.book[*].title
// Returns: all book titles
All properties:
$.*
// Returns: all top-level properties
Recursive Descent
The .. operator searches through all levels:
$..price
// Returns: all price values at any level
$..book[*].author
// Returns: all authors from book arrays at any level
Example with nested data:
{
"company": {
"departments": [
{
"name": "Engineering",
"employees": [
{"name": "John", "salary": 80000},
{"name": "Jane", "salary": 90000}
]
}
]
}
}
$..salary
// Returns: [80000, 90000]
Filtering
Filters allow you to select elements based on conditions.
Filter Syntax
$..book[?(@.price < 30)]
// Books with price less than 30
$..book[?(@.author == 'John')]
// Books by John
Comparison Operators
| Operator | Description | Example |
|---|---|---|
== |
Equal | ?(@.price == 10) |
!= |
Not equal | ?(@.price != 10) |
< |
Less than | ?(@.price < 30) |
<= |
Less or equal | ?(@.price <= 30) |
> |
Greater than | ?(@.price > 30) |
>= |
Greater or equal | ?(@.price >= 30) |
=~ |
Regex match | ?(@.title =~ /java.*/) |
Logical Operators
AND condition:
$..book[?(@.price > 20 && @.price < 40)]
// Books with price between 20 and 40
OR condition:
$..book[?(@.category == 'fiction' || @.category == 'science')]
// Fiction or science books
NOT condition:
$..book[?(!@.isbn)]
// Books without ISBN
Existence Checks
$..book[?(@.isbn)]
// Books that have ISBN field
$..book[?(@.discount)]
// Books with discount
Practical Examples
Example 1: API Response
{
"users": [
{
"id": 1,
"name": "John",
"email": "john@example.com",
"active": true,
"roles": ["admin", "user"]
},
{
"id": 2,
"name": "Jane",
"email": "jane@example.com",
"active": false,
"roles": ["user"]
}
]
}
Queries:
// All user names
$.users[*].name
// Result: ["John", "Jane"]
// Active users
$.users[?(@.active == true)]
// Result: [{ id: 1, name: "John", ... }]
// Admins
$.users[?(@.roles[*] == 'admin')]
// Result: [{ id: 1, name: "John", ... }]
// Email of first user
$.users[0].email
// Result: "john@example.com"
Example 2: E-commerce Data
{
"store": {
"products": [
{
"id": 1,
"name": "Laptop",
"price": 999,
"stock": 5,
"category": "electronics"
},
{
"id": 2,
"name": "Mouse",
"price": 25,
"stock": 50,
"category": "electronics"
},
{
"id": 3,
"name": "Desk",
"price": 299,
"stock": 0,
"category": "furniture"
}
]
}
}
Queries:
// Products under $100
$.store.products[?(@.price < 100)]
// Out of stock items
$.store.products[?(@.stock == 0)]
// Electronics in stock
$.store.products[?(@.category == 'electronics' && @.stock > 0)]
// All product names
$.store.products[*].name
// Expensive electronics
$.store.products[?(@.category == 'electronics' && @.price > 500)]
Example 3: Nested API Response
{
"data": {
"posts": [
{
"id": 1,
"title": "First Post",
"author": {
"name": "John",
"verified": true
},
"comments": [
{"text": "Great!", "likes": 5},
{"text": "Thanks", "likes": 2}
]
},
{
"id": 2,
"title": "Second Post",
"author": {
"name": "Jane",
"verified": false
},
"comments": [
{"text": "Nice", "likes": 10}
]
}
]
}
}
Queries:
// All post titles
$.data.posts[*].title
// Posts by verified authors
$.data.posts[?(@.author.verified == true)]
// All comments
$..comments[*]
// Comments with more than 3 likes
$..comments[?(@.likes > 3)]
// Names of all authors
$.data.posts[*].author.name
// All likes values
$..likes
Advanced Techniques
Functions
Some JSONPath implementations support functions:
// Length of array
$.store.products.length()
// Min/Max values
$.store.products[*].price.min()
$.store.products[*].price.max()
// Average
$.store.products[*].price.avg()
Script Expressions
// Complex conditions
$.store.products[?(@.price * @.stock > 1000)]
// Mathematical operations
$.store.products[?(@.price > (@.originalPrice * 0.8))]
Multiple Conditions
// Complex filtering
$..products[?(
@.category == 'electronics' &&
@.stock > 0 &&
@.price < 1000 &&
@.rating >= 4
)]
Common Use Cases
1. API Testing
Validate API responses:
// Check if user is admin
$.user.roles[?(@=='admin')]
// Verify all products have prices
$.products[*].price
// Check for errors
$..error
2. Data Transformation
Extract specific fields:
// Get user IDs and emails only
$.users[*]['id','email']
// Extract nested data
$..orders[*].items[*].name
3. Monitoring & Logging
Query log structures:
// Find error logs
$..logs[?(@.level == 'error')]
// Get timestamps of warnings
$..logs[?(@.level == 'warn')].timestamp
4. Configuration Management
Navigate config files:
// Database settings
$.config.database
// All enabled features
$..features[?(@.enabled == true)].name
JSONPath vs Other Query Languages
JSONPath vs XPath
XPath (XML):
//book[@price < 30]/title
JSONPath (JSON):
$..book[?(@.price < 30)].title
JSONPath vs SQL
SQL:
SELECT name FROM users WHERE age > 18
JSONPath:
$.users[?(@.age > 18)].name
JSONPath vs jq
jq:
.users[] | select(.age > 18) | .name
JSONPath:
$.users[?(@.age > 18)].name
Implementation Libraries
JavaScript
const jsonpath = require('jsonpath');
const result = jsonpath.query(data, '$.users[*].name');
Python
from jsonpath_ng import parse
expression = parse('$.users[*].name')
results = [match.value for match in expression.find(data)]
Java
List<String> names = JsonPath.read(json, "$.users[*].name");
Go
import "github.com/oliveagle/jsonpath"
res, err := jsonpath.JsonPathLookup(data, "$.users[*].name")
Best Practices
-
Start simple and build up
- Test basic paths first
- Add complexity gradually
-
Use specific paths when possible
// Specific (faster) $.users[0].name // General (slower) $..name -
Validate your paths
- Test with sample data
- Handle empty results
-
Consider performance
- Recursive descent (
..) can be slow - Filter early in the path
- Recursive descent (
-
Document complex expressions
// Get active premium users with recent activity $.users[?( @.active == true && @.plan == 'premium' && @.lastActivity > '2025-01-01' )]
Common Pitfalls
1. Array vs Object Confusion
// Wrong - treating object as array
$.user[0].name
// Correct
$.user.name
2. Incorrect Filter Syntax
// Wrong - missing @ symbol
$..book[?(price < 30)]
// Correct
$..book[?(@.price < 30)]
3. String Comparison
// Wrong - number comparison on string
$..book[?(@.isbn > 1000)]
// Correct - string comparison
$..book[?(@.isbn)]
Conclusion
JSONPath is a powerful tool for querying JSON data. Whether you're testing APIs, transforming data, or navigating complex structures, mastering JSONPath will make you more efficient.
Key takeaways:
- Start with
$for root - Use
.for child navigation - Use
..for recursive search - Use filters
[?()]for conditional selection - Practice with real-world examples
The more you use JSONPath, the more natural it becomes. Start with simple queries and gradually tackle more complex scenarios as you build confidence.
Try JSONPath Tester Now
Ready to put this into practice? Use our free JSONPath Tester tool. It works entirely in your browser with no signup required.
Launch JSONPath TesterFrequently Asked Questions
Q Is JSONPath part of the JSON spec?
No. JSONPath is a separate query language; implementations differ slightly between libraries.
Related Articles
Understanding JSON Formatting and Validation
A comprehensive guide to JSON format, why it matters, and how to format and validate JSON effectively for better code readability and debugging.
Mastering Regular Expressions - Complete Guide to Regex Patterns
Learn everything about regular expressions, how they work, common patterns, and best practices for pattern matching, validation, and text processing.
Understanding URL Encoding - Complete Guide to Percent Encoding
Learn everything about URL encoding (percent-encoding), how it works, when to use it, and best practices for encoding URLs and URI components safely.
Understanding Base64 Encoding - Complete Guide
Learn everything about Base64 encoding, how it works, when to use it, and best practices for encoding and decoding binary data in text formats.