JSON Wallet

Querying JSON with JSONPath

9 min read

← All guides

When an API returns a large, deeply nested response, walking it field by field in code is tedious. JSONPath is a small query language — think XPath, but for JSON — that lets you extract exactly the values you want with a single compact expression. It is supported in many libraries, command-line tools, and platforms like AWS and Kubernetes.

The sample data

We will query this document throughout:

{
  "store": {
    "books": [
      { "title": "JSON Basics", "price": 12, "tags": ["intro"] },
      { "title": "Advanced JSON", "price": 30, "tags": ["intro", "deep"] },
      { "title": "JSON at Scale", "price": 45, "tags": ["deep"] }
    ],
    "open": true
  }
}

The fundamentals

  • $ — the root of the document. Every path starts here.
  • .key or ['key'] — a child property by name.
  • [n] — an array element by index (zero-based).
  • * — a wildcard matching all children.
  • .. — a recursive descent that searches at any depth.

Selecting values

$.store.open
// → true

$.store.books[0].title
// → "JSON Basics"

$.store.books[*].title
// → ["JSON Basics", "Advanced JSON", "JSON at Scale"]

$..title
// → every "title" anywhere in the document

The recursive $..title is especially handy when you do not know, or do not care, how deeply a field is nested — it finds every title in the tree.

Array slices

JSONPath borrows Python-style slicing: [start:end] (end exclusive), with negative indices counting from the end.

$.store.books[0:2]
// → the first two books

$.store.books[-1:]
// → the last book

$.store.books[:2].title
// → titles of the first two books

Filter expressions

The most powerful feature is filtering with ?(), where @ refers to the current element being tested.

$.store.books[?(@.price < 20)].title
// → ["JSON Basics"]

$.store.books[?(@.price >= 30)].title
// → ["Advanced JSON", "JSON at Scale"]

$.store.books[?(@.tags.indexOf('deep') != -1)].title
// → books tagged "deep"

Filters turn JSONPath from a navigation tool into a genuine query language: "give me the titles of every book under $20" becomes one line.

Where you will use it

  • Command line: tools accept JSONPath to extract values from API output in scripts.
  • Kubernetes: kubectl get ... -o jsonpath=... pulls fields out of resource JSON.
  • AWS: the CLI's --query and Step Functions use JSONPath to pick values.
  • Testing: API test frameworks assert on JSONPath expressions against responses.

A note on dialects

JSONPath was never as tightly standardised as XPath, so implementations differ slightly — especially around filters, the exact behaviour of .., and whether results are returned as a list or a single value. RFC 9535 (published in 2024) finally standardised the syntax, but older libraries predate it. When a query behaves unexpectedly, check your specific library's documentation.

Frequently asked questions

What is the difference between JSONPath and jq?

JSONPath is a query/selection syntax. jq is a full command-line program and language that can select, transform, reshape and compute over JSON. JSONPath is simpler and embedded in many tools; jq is more powerful for ad-hoc data wrangling.

Does JSONPath modify the data?

No. JSONPath only reads — it selects and returns values. To transform data you need a tool like jq or code in your language of choice.

Why does the same expression return different results in two tools?

Because of dialect differences that predate RFC 9535. Filter syntax and recursive descent are the usual culprits. Prefer libraries that advertise RFC 9535 compliance for consistent behaviour.

Explore your JSON first

Before writing a JSONPath query it helps to understand the structure you are querying. Paste your document into the JSON Wallet editor and use the tree view to map out the nesting, then write your path against it. New to nested data? Read What is JSON? first.


Keep reading

Ready to put this into practice? Open the free JSON editor →