What it is
JSON is a lightweight data-interchange format that is easy for humans to read and write and easy for machines to parse and generate. JSONPath is a query language for JSON, similar to XPath for XML.
Installation
JSON is a data format, not a tool that needs installation. Most programming languages have built-in support for parsing and generating JSON.
JSONPath implementations are typically libraries within programming languages. Here are common ways to use JSONPath:
JavaScript (Node.js/Browser):
npm install jsonpath
# or
yarn add jsonpath
Import into your project:
const jsonpath = require('jsonpath');
// or
import jsonpath from 'jsonpath';
Python:
pip install jsonpath-ng
Import into your project:
from jsonpath_ng import jsonpath, parse
Command Line (using jq and jsonpath-ng for piping):
jq is a powerful command-line JSON processor. While jq has its own powerful filtering language, you can pipe JSON to jq which can then be processed by a JSONPath library.
Install jq:
# Linux (Debian/Ubuntu)
sudo apt-get update && sudo apt-get install jq
# Linux (Fedora)
sudo dnf install jq
# macOS
brew install jq
# Windows (using Chocolatey)
choco install jq
Core Concepts
- JSON Structure: JSON data is built on two structures:
- Objects: A collection of key/value pairs. Keys are strings, values can be strings, numbers, booleans, arrays, objects, or null. Enclosed in curly braces
{}. - Arrays: An ordered list of values. Values can be any valid JSON type. Enclosed in square brackets
[].
- Objects: A collection of key/value pairs. Keys are strings, values can be strings, numbers, booleans, arrays, objects, or null. Enclosed in curly braces
- JSONPath Syntax: JSONPath expressions select nodes within a JSON document.
- Root:
$represents the root object/element. - Dot Notation:
.is used to access object members by key (e.g.,$.store.book[0].title). - Bracket Notation:
[]is used to access object members by key or array elements by index. It’s also used for wildcards and filters (e.g.,$.store['book'][0].title). - Wildcard:
*selects all elements in an object or array. - Recursive Descent:
..selects all descendants of the current node. - Array Slice:
[start:end:step]selects a range of array elements. - Filter Expression:
?()filters elements based on a condition.
- Root:
Commands / Usage
This section focuses on how to use JSONPath expressions. The examples assume you have a JSON object available.
Example JSON Data:
{
"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": 19.95
}
},
"expensive": 10
}
Selecting Elements
-
Select the root element:
$Explanation: Returns the entire JSON document.
-
Select the
storeobject:$.storeExplanation: Returns the object under the
storekey. -
Select the
bookarray:$.store.bookExplanation: Returns the array under the
bookkey withinstore. -
Select the first book in the array:
$.store.book[0]Explanation: Returns the first element (index 0) of the
bookarray. -
Select the title of the first book:
$.store.book[0].titleExplanation: Returns the
titleproperty of the first book. -
Select the title of the second book using bracket notation:
$.store.book['1']['title']Explanation: Equivalent to
$.store.book[1].title, using bracket notation for both array index and object key.
Wildcards and Recursive Descent
-
Select all books:
$.store.book[*]Explanation: Returns all elements within the
bookarray. -
Select all authors of all books:
$.store.book[*].authorExplanation: Returns the
authorproperty for every element in thebookarray. -
Select all titles of all books (using recursive descent):
$..titleExplanation: Returns all values associated with the
titlekey anywhere in the document. -
Select all prices from the store (books and bicycle):
$.store..priceExplanation: Returns all
pricevalues found within thestoreobject and its descendants.
Array Slicing
-
Select books from index 1 onwards:
$.store.book[1:]Explanation: Returns elements from index 1 to the end of the
bookarray. -
Select books up to (but not including) index 2:
$.store.book[:2]Explanation: Returns elements from the beginning up to (but not including) index 2.
-
Select books from index 1 up to (but not including) index 3:
$.store.book[1:3]Explanation: Returns elements from index 1 up to (but not including) index 3.
-
Select every second book:
$.store.book[::2]Explanation: Returns elements with a step of 2 (0th, 2nd, etc.).
-
Select books from index 1 with a step of 2:
$.store.book[1::2]Explanation: Returns elements starting from index 1 with a step of 2 (1st, 3rd, etc.).
Filter Expressions
-
Select all books with a price less than 10:
$.store.book[?(@.price < 10)]Explanation: Filters the
bookarray, returning only elements where thepriceis less than 10.@refers to the current element being processed. -
Select all books with a price greater than or equal to 10:
$.store.book[?(@.price >= 10)]Explanation: Filters the
bookarray for prices greater than or equal to 10. -
Select all fiction books:
$.store.book[?(@.category == 'fiction')]Explanation: Filters the
bookarray for elements where thecategoryis 'fiction'. -
Select all books by Evelyn Waugh:
$.store.book[?(@.author == 'Evelyn Waugh')]Explanation: Filters the
bookarray for the specific author. -
Select all books that have an ISBN:
$.store.book[?(@.isbn)]Explanation: Filters the
bookarray, returning elements that have anisbnkey (even if its value is null or empty, it must exist). -
Select the titles of all books with a price less than 10:
$.store.book[?(@.price < 10)].titleExplanation: First filters for books under $10, then selects the
titlefrom the resulting books. -
Select books with price less than 10 OR category is reference:
$.store.book[?(@.price < 10 || @.category == 'reference')]Explanation: Uses the OR operator
||to combine conditions. -
Select books with price less than 10 AND category is fiction:
$.store.book[?(@.price < 10 && @.category == 'fiction')]Explanation: Uses the AND operator
&&to combine conditions. -
Select books with price between 10 and 20 (inclusive):
$.store.book[?(@.price >= 10 && @.price <= 20)]Explanation: Uses a range check with AND operators.
Combining Expressions
-
Select the author of the first book:
$.store.book[0].authorExplanation: Direct path selection.
-
Select the price of the bicycle:
$.store.bicycle.priceExplanation: Direct path selection.
-
Select all items that have a price (books and bicycle):
$..*[?(@.price)]Explanation: This is a bit broad. It looks for any object
*that has apricekey. A more precise way for this specific JSON might be$.store.book[?(@.price)]and$.store.bicycle. For a general solution across unknown structures, recursive descent is often used. -
Select the titles of all books where the author is Herman Melville or J. R. R. Tolkien:
$.store.book[?(@.author == 'Herman Melville' || @.author == 'J. R. R. Tolkien')].titleExplanation: Filters for specific authors and then extracts their titles.
Common Patterns
-
Using
jqto pipe JSON and filter with JSONPath expressions: Whilejqhas its own powerful filtering language, you can combine it with JSONPath logic by usingjqto extract parts of the JSON and then processing those parts. For direct JSONPath queries on the command line, tools likejsonpath-clior Python scripts are common.Example using
jqto select titles of books with price > 10:echo '{ "store": { "book": [ {"title": "Book A", "price": 5}, {"title": "Book B", "price": 15} ] } }' | jq '.store.book[] | select(.price > 10) | .title'Explanation: This uses
jq’s own filtering. For a pure JSONPath command-line tool, you’d typically pipe the JSON to that tool.Example using a Python script for JSONPath on the command line: Save the following as
jp.py:import sys import json from jsonpath_ng import jsonpath, parse if __name__ == "__main__": data = json.load(sys.stdin) jsonpath_expression_str = sys.argv[1] jsonpath_expression = parse(jsonpath_expression_str) matches = jsonpath_expression.find(data) results = [match.value for match in matches] print(json.dumps(results, indent=2))Then run:
echo '{ ... your json ... }' | python jp.py "$.store.book[?(@.price > 10)].title"Explanation: This script reads JSON from stdin, takes a JSONPath expression as a command-line argument, and prints the results as JSON.
-
Extracting all keys from an object:
$.store.*Explanation: Selects all values directly under
store. If you want the keys themselves, you’d typically use programmatic iteration or a tool likejq(jq 'keys'). -
Finding a specific book by ISBN:
$.store.book[?(@.isbn == '0-553-21311-3')]Explanation: Filters the book array to find the book with a matching ISBN.
-
Getting the price of the most expensive book: This requires a two-step process or a more advanced JSONPath implementation that supports aggregation or sorting, which is not standard. A common approach is to filter and then process the results.
First, get all book prices:
$.store.book[*].priceThen, use a programming language or tool to find the maximum value from the resulting list.
Using
jqto find the max price:echo '{ ... your json ... }' | jq '[.store.book[].price] | max'Explanation:
jqextracts all prices into an array[...]and then applies themaxfunction.
Gotchas
- Implementation Differences: JSONPath is a specification, and different libraries (e.g.,
jsonpath-ngin Python,jsonpathin JavaScript) might have slight variations in syntax or feature support, especially for advanced filtering or recursive descent. Always check the documentation for your specific implementation. - Filter Expression Syntax (
@): The@symbol within filter expressions?()refers to the current node being processed. Forgetting it or misplacing it is a common error. - Recursive Descent (
..) Performance: While powerful,..can be computationally expensive on very large or deeply nested JSON structures as it traverses the entire tree. Use it judiciously. - Return Type: Some JSONPath implementations might return a list of matches even if only one item is expected. Always be prepared to handle a list, even if you query for a single specific element.
- Boolean Logic in Filters: Ensure correct use of
&&(AND) and||(OR) operators within filter expressions. Parentheses()can be used for grouping conditions if needed, though support varies. - Array Indexing: JSONPath array indexing is 0-based, just like in most programming languages.
- Quoting in Filters: String literals within filter expressions must be quoted (e.g.,
'fiction'). Numeric literals do not need quotes. - Dot vs. Bracket Notation: While often interchangeable for simple property access (e.g.,
$.store.bookvs$.store['book']), bracket notation is essential when keys contain special characters or spaces, or when using variables as keys.