JSONPath is a query language for extracting data from JSON documents, analogous to how XPath queries XML. Originally proposed by Stefan Goessner in 2007, JSONPath has become a widely used standard for navigating and selecting elements within JSON structures.
In an era where JSON is the dominant data interchange format for APIs, configuration files, and data storage, the ability to precisely query JSON data is essential. JSONPath provides a concise, expressive syntax for selecting specific values, filtering arrays, and navigating deeply nested structures without writing custom parsing code.
JSONPath is supported in a wide ecosystem of tools and languages: JavaScript (jsonpath, jsonpath-plus), Python (jsonpath-ng, jsonpath-rw), Java (Jayway JsonPath), PHP (JsonPath), Kubernetes (kubectl), Postman, and many API testing frameworks. In 2023, JSONPath was formalized as RFC 9535, providing an official standard after years of implementation-specific variations.
A simple example: given a JSON document containing user data, the JSONPath expression $.users[0].name extracts the name of the first user. More complex expressions can filter arrays by conditions, search recursively through nested structures, and select multiple paths simultaneously.
JSONPath expressions always start with $, which represents the root of the JSON document. From there, you build paths using operators that navigate the structure.
Operator Description Example
$ Root object/element $
.property Child property (dot notation) $.store
['property'] Child property (bracket notation) $['store']
[n] Array element by index $[0]
[start:end] Array slice $[0:3]
* Wildcard (all children) $.store.*
.. Recursive descent $..author
[?()] Filter expression $[?(@.price<10)]
[,] Union (multiple indices/names) $[0,2,4]
Most JSONPath examples use a variation of the classic "bookstore" document. We will use this throughout the guide:
{
"store": {
"book": [
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 399.99
}
}
}
JSONPath offers two ways to access child properties: dot notation and bracket notation. Both achieve the same result for simple property names.
Dot notation is concise and familiar to JavaScript developers:
$.store.book -- the book array
$.store.bicycle.color -- "red"
$.store.book[0].author -- "Nigel Rees"
$.store.book[0].title -- "Sayings of the Century"
Bracket notation uses quoted property names inside square brackets:
$['store']['book'] -- the book array
$['store']['bicycle']['color'] -- "red"
$['store']['book'][0]['author'] -- "Nigel Rees"
Bracket notation is required when property names contain special characters, spaces, hyphens, or start with digits:
// Properties with special characters
$['first-name'] -- hyphenated property
$['my property'] -- property with space
$['123'] -- property starting with digit
$['@type'] -- property with @ symbol
// Dot notation would FAIL for these:
$.first-name -- interpreted as $.first minus name
$.my property -- syntax error
$.123 -- ambiguous (number or property?)
The wildcard operator * matches all children of the current element. It works on both objects (all property values) and arrays (all elements).
$.store.* -- all things in the store (book array + bicycle object)
$.store.book[*] -- all books
$.store.book[*].author -- all authors: ["Nigel Rees", "Evelyn Waugh",
"Herman Melville", "J. R. R. Tolkien"]
$.* -- all top-level values
The union operator selects multiple specific indices or property names in a single expression:
// Multiple array indices
$.store.book[0,2] -- first and third books
// Multiple properties (some implementations)
$.store.book[0]['title','author'] -- title and author of first book
// Multiple indices with different spacing
$.store.book[0, 1, 3] -- first, second, and fourth books
The recursive descent operator (..) is one of JSONPath's most powerful features. It searches the entire document tree for matching property names, regardless of depth.
$..author -- ALL author values anywhere in the document
-- ["Nigel Rees", "Evelyn Waugh", "Herman Melville", "J. R. R. Tolkien"]
$..price -- ALL price values (books + bicycle)
-- [8.95, 12.99, 8.99, 22.99, 399.99]
$..isbn -- ALL isbn values (only books that have isbn)
-- ["0-553-21311-3", "0-395-19395-8"]
$..book[0] -- first book (found via recursive search for "book")
$..* -- ALL values at ALL levels (entire document flattened)
Recursive descent is particularly useful when:
Recursive descent searches the entire document tree, which can be expensive for large JSON documents. Use specific paths when you know the structure, and reserve recursive descent for exploration or cases where the path is genuinely variable.
JSONPath supports flexible array access through indexing and slicing, similar to Python's list slicing.
$.store.book[0] -- first book (index 0)
$.store.book[1] -- second book (index 1)
$.store.book[-1] -- last book (negative indexing)
$.store.book[-2] -- second-to-last book
Slicing uses the syntax [start:end:step], where start is inclusive, end is exclusive, and step is the increment. All three are optional.
$.store.book[0:2] -- first two books (index 0 and 1)
$.store.book[1:3] -- second and third books
$.store.book[:2] -- first two books (start defaults to 0)
$.store.book[2:] -- from third book to end
$.store.book[-2:] -- last two books
$.store.book[::2] -- every other book (step of 2)
$.store.book[::-1] -- all books in reverse order
Given array: ["a", "b", "c", "d", "e"]
$[0:3] -- ["a", "b", "c"] (indices 0, 1, 2)
$[1:4] -- ["b", "c", "d"] (indices 1, 2, 3)
$[:2] -- ["a", "b"] (first 2)
$[3:] -- ["d", "e"] (from index 3 to end)
$[-2:] -- ["d", "e"] (last 2)
$[0:5:2] -- ["a", "c", "e"] (every other, starting at 0)
$[1:5:2] -- ["b", "d"] (every other, starting at 1)
Filter expressions allow you to select array elements or object properties based on conditions. They use the syntax [?(@.property operator value)], where @ refers to the current element being evaluated.
== Equal to
!= Not equal to
< Less than
<= Less than or equal to
> Greater than
>= Greater than or equal to
// Books cheaper than 10
$.store.book[?(@.price < 10)]
// Returns books by Nigel Rees (8.95) and Herman Melville (8.99)
// Fiction books only
$.store.book[?(@.category == 'fiction')]
// Returns books by Evelyn Waugh, Herman Melville, J. R. R. Tolkien
// Books with ISBN
$.store.book[?(@.isbn)]
// Returns books that have an isbn property (Moby Dick, Lord of the Rings)
// Books by a specific author
$.store.book[?(@.author == 'Herman Melville')]
// Returns the Moby Dick book object
// Expensive books (price >= 20)
$.store.book[?(@.price >= 20)]
// Returns The Lord of the Rings (22.99)
// Books NOT in the fiction category
$.store.book[?(@.category != 'fiction')]
// Returns Sayings of the Century (reference)
Some implementations support logical operators within filters:
// Books that are fiction AND cost less than 15
$.store.book[?(@.category == 'fiction' && @.price < 15)]
// Books that are reference OR cost more than 20
$.store.book[?(@.category == 'reference' || @.price > 20)]
// Negation
$.store.book[?(!@.isbn)]
// Books without an isbn property
Note that logical operator support varies between implementations. RFC 9535 standardizes && (logical AND), || (logical OR), and ! (logical NOT) for filter expressions.
// Check if a property exists
$.store.book[?(@.isbn)] -- books that have an isbn property
$.store.book[?(@.discount)] -- books that have a discount property
// This works because @.isbn evaluates to a truthy value if the
// property exists and has a value, or falsy if it does not exist.
Here are practical JSONPath examples for common real-world JSON structures.
// GitHub API response
{
"items": [
{
"full_name": "facebook/react",
"stargazers_count": 220000,
"language": "JavaScript",
"topics": ["javascript", "frontend", "ui"]
},
...
]
}
// All repository names
$.items[*].full_name
// Repos with 100k+ stars
$.items[?(@.stargazers_count > 100000)].full_name
// All topics from all repos
$.items[*].topics[*]
// kubectl uses JSONPath extensively
# Get all pod names
kubectl get pods -o jsonpath='{.items[*].metadata.name}'
# Get all container images
kubectl get pods -o jsonpath='{.items[*].spec.containers[*].image}'
# Get pod name and status
kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.phase}{"\n"}{end}'
# Get nodes with their addresses
kubectl get nodes -o jsonpath='{.items[*].status.addresses[?(@.type=="InternalIP")].address}'
// Package.json
{
"name": "my-app",
"dependencies": {
"react": "^18.2.0",
"axios": "^1.6.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test"
}
}
// All dependency names (keys)
// Note: JSONPath key extraction varies by implementation
// Get specific script
$.scripts.build -- "react-scripts build"
// Check if a dependency exists
$.dependencies.react -- "^18.2.0"
// E-commerce order
{
"order": {
"id": "ORD-001",
"customer": {
"name": "Alice",
"address": {
"city": "New York",
"state": "NY"
}
},
"items": [
{"product": "Widget", "qty": 2, "price": 9.99},
{"product": "Gadget", "qty": 1, "price": 24.99}
]
}
}
// Customer city
$.order.customer.address.city -- "New York"
// All product names
$.order.items[*].product -- ["Widget", "Gadget"]
// Items costing more than 10
$.order.items[?(@.price > 10)] -- [{"product":"Gadget",...}]
// Total item count (need to process result)
$.order.items.length() -- 2 (implementation-dependent)
Several tools and languages exist for querying JSON data. Understanding the differences helps you choose the right tool for each situation.
Feature JSONPath jq
Purpose Query/extract Query + transform + construct
Syntax $.store.book[0] .store.book[0]
Filtering [?(@.price<10)] select(.price < 10)
Transformation Limited Full (map, reduce, group_by)
Conditionals Filter only if-then-else
Functions Minimal Rich built-in library
Standalone tool No (library) Yes (CLI tool)
Embedded use APIs, libraries CLI, scripts
Learning curve Low Medium-High
Use JSONPath when you need simple data extraction within an application or API. Use jq when you need complex transformation, data reshaping, or command-line JSON processing.
JSONPath XPath Purpose
$ / Root
$.store /store Child
$..author //author Recursive descent
$.store.book[0] /store/book[1] Array index (0 vs 1 based)
$.store.book[*] /store/book All elements
[?(@.price<10)] [price<10] Filter
@ . Current node
JSONPath was designed as a JSON analog of XPath, with syntax adapted for JSON's structure. The most notable difference is that JSONPath uses zero-based array indexing while XPath uses one-based.
JSONPath JSON Pointer Notes
$.store.book[0] /store/book/0 Pointer uses / separator
$.store.bicycle /store/bicycle Simpler syntax in Pointer
$..author (not supported) No recursive descent
[?(@.price<10)] (not supported) No filtering
$.store.* (not supported) No wildcards
JSON Pointer is a simpler, more limited specification designed for addressing a single value within a JSON document. It is used in JSON Patch (RFC 6902) and JSON Schema references. JSONPath is more expressive but more complex.
Our JSONPath Tester lets you paste any JSON document and test JSONPath expressions interactively. See results instantly as you type your expression, with syntax highlighting for both the JSON input and the matched results.
The tool supports all standard JSONPath operators including dot notation, bracket notation, recursive descent, array slicing, wildcards, unions, and filter expressions. It highlights matched elements in the source JSON, provides expression auto-completion hints, and includes a library of example expressions to help you learn the syntax.
Whether you are building API integrations, writing Kubernetes JSONPath queries, extracting data from complex JSON responses, or learning JSONPath syntax, this tester provides instant feedback and makes experimentation easy.
JSONPath is a query language for JSON data, analogous to XPath for XML. It uses expressions starting with $ (root) to navigate and extract values from JSON structures. It supports dot/bracket notation, wildcards, recursive descent, filtering, and array slicing.
Dot notation ($.store.book) is concise for simple property names. Bracket notation ($['store']['book']) handles special characters, spaces, and reserved words in property names. Both produce the same result for standard names.
The .. operator searches the entire JSON tree for a property name at any depth. $..author finds all "author" values regardless of where they appear in the hierarchy.
Use filter expressions: [?(@.property operator value)]. The @ symbol refers to the current element. Example: $.store.book[?(@.price < 10)] returns all books priced under 10.
Array slicing uses [start:end:step] to select ranges. $[0:3] selects the first three elements, $[-2:] selects the last two, and $[::2] selects every other element.
JSONPath is a query language for extracting data, while jq is a full JSON processor with transformation, construction, and programming features. JSONPath is simpler and embedded in libraries/APIs; jq is more powerful as a standalone CLI tool.