JSONPath Tester: Query and Extract Data from JSON Instantly
Test JSONPath expressions against real JSON and see every matching node with its normalized path. Free JSONPath evaluator with wildcards and filters — runs entirely client-side.
Try it now: JSONPath Tester — Run a JSONPath expression against a document and see every matching node with its normalized path — filters, wildcards and recursive descent included.
What JSONPath Is For
JSONPath is a query language for pulling specific values out of a JSON document without writing a loop, an.filter(), or a chain of optional-chaining lookups to get there. Instead of walking a response by hand — data.users[2].address.city and hoping index 2is still the right one next time the API returns data — you write one expression that describes the shape of what you're looking for, and a JSONPath evaluator returns every node in the document that matches it. That matters most on documents you don't fully control the shape of: a third-party API response, a large generated config file, a log line dumped as JSON. Before an expression can match anything, the document has to actually be valid JSON — if you're starting from a raw paste that hasn't been checked or pretty-printed yet, the JSON Formatter guide covers validating and formatting it first.
Core JSONPath Syntax
Every JSONPath expression starts at $, the root of the document, and narrows from there with a small set of operators:
.— child access by key, e.g.$.user.name.[]— bracket access, for keys that aren't valid identifiers or for array indices, e.g.$.users[0]or$["user-id"].*— the wildcard, matching every child of the current node regardless of key or index, e.g.$.users[*].namefor every user's name...— recursive descent, searching every level of the document below the current node instead of just the immediate children, e.g.$..emailto find anemailfield wherever it appears, at any depth.[?(@.field==value)]— a filter expression, keeping only the array elements where the condition inside is true.@refers to the current element being tested.
{
"users": [
{ "id": 1, "name": "Ada", "active": true, "role": "admin" },
{ "id": 2, "name": "Grace", "active": false, "role": "engineer" },
{ "id": 3, "name": "Alan", "active": true, "role": "engineer" }
]
}matched 2 nodes $.users[0].name → "Ada" $.users[2].name → "Alan"
Practical Use Cases
- Extracting fields from an API response. A response body nested four or five levels deep — pagination wrapper, data envelope, array of records — turns into one expression like
$.data.items[*].idinstead of a defensive chain of null checks. - Querying a large config or infrastructure file. Recursive descent is the useful one here:
$..regionfinds everyregionkey in a deeply nested Terraform-style JSON export, regardless of how many layers of nesting separate one occurrence from another. - Filtering an array of records by a condition. A JSONPath filter such as
$.orders[?(@.status=="failed")]answers “which of these” directly, which is the most common reason people go looking for a JSONPath filter in the first place — they don't want the whole array, they want the subset that matches one condition.
There Is No Single JSONPath Spec — Verify, Don't Guess
The one thing worth being exact about: JSONPath does not have a single, universally implemented specification the way JSON itself does. The original 2007 proposal described the core syntax, but filter expressions, negative array indices, and multiple-key selection were never pinned down precisely, so different libraries diverge on edge cases — one implementation accepts [?(@.price < 10)] with spaces around the operator, another doesn't; some support [-1]for the last array element, others don't; quoting rules inside filter strings vary too. RFC 9535, published in 2024, standardizes a lot of this, but plenty of tools you'll run into still predate it or intentionally diverge from it. The practical consequence: don't trust a JSONPath expression by reading it — test JSONPath expressions against the actual document and look at what actually matched. A gotcha worth internalizing is that a filter expression can silently match zero nodes on a typo (a misspelled field name, a stray space, a comparison against the wrong type) rather than throwing an error, so “it parsed” is not the same guarantee as “it matched what I meant.”
expression: $.users[?(@.Active==true)]
(note the capital "A" — the field is "active")
matched 0 nodesA JSONPath tester makes that check trivial by showing every matching node alongside its normalized path, so you can see at a glance whether an expression matched three nodes or zero, and exactly which ones, before that expression ships inside application code. GenKitLab's JSONPath Tester runs an expression against a document and lists every matching node with its normalized path — filters, wildcards, and recursive descent all included — entirely client-side, so nothing you paste is uploaded anywhere. If the document itself needs cleaning up first, JSON Formatter handles validating and pretty-printing it before you start querying.
Frequently asked questions
›What is JSONPath used for?
It's a query language for extracting specific values out of a JSON document by describing their shape or position, instead of writing imperative code — a loop, a filter, a chain of optional-chaining lookups — to find them by hand. It's most useful on documents whose exact shape you don't fully control, like a third-party API response.
›What does the JSONPath wildcard (*) do?
It matches every child of the current node regardless of its key or array index. $.users[*].name returns the name field from every element in the users array, whatever length that array happens to be.
›What's the difference between . and .. in JSONPath?
A single dot (.) accesses an immediate child by key. Double dots (..) trigger recursive descent — the expression searches every level below the current node, not just the direct children, so $..email finds an email field no matter how deeply it's nested.
›How do JSONPath filter expressions work?
A filter, written as [?(@.field==value)], keeps only the array elements where the condition inside evaluates to true. @ refers to the element currently being tested. $.orders[?(@.status=="failed")] returns only the orders whose status field equals "failed".
›Is JSONPath standardized the same way JSON is?
No, and this is the most important thing to know before relying on one. The original 2007 proposal left filter syntax, negative indices, and quoting rules underspecified, so implementations diverge on edge cases. RFC 9535 (2024) formalizes a standard, but many tools predate it or diverge intentionally — always test an expression against real data rather than assuming it will behave identically everywhere.
›Why did my JSONPath filter match zero nodes instead of erroring?
A filter expression with a typo — a misspelled field name, wrong capitalization, a comparison against the wrong type — is still syntactically valid JSONPath, so it parses fine and simply matches nothing. That's why a tester that shows you the actual matched nodes is safer than trusting an expression by reading it.
Last updated