JSON path tester · Guide
JSONPath Syntax Explained: Roots, Filters, Wildcards and Recursive Descent
JSONPath selects values from a JSON document with expressions that resemble property access. `$` denotes the root, dot or bracket notation selects children, brackets address array positions, and filters choose elements by a condition. The core syntax is portable, but filter operators, functions and result shapes vary between implementations, so test expressions with the same library used in production and distinguish no match from a matched JSON `null`.
Start at the root and select child members
The dollar sign represents the whole input document. A dot followed by a member name selects an object child, so $.store.book walks from the root to store and then book. Some tools allow a relative expression without $, but including it makes the starting point explicit.
{
"store": {
"book": [
{"title": "A", "price": 8.99},
{"title": "B", "price": 12.50}
]
}
}
$.store.bookA path selects nodes, not a textual substring. The result may be one object, several values or an empty collection depending on the expression and library API. Do not assume every successful query returns a scalar.
Property names are case-sensitive because JSON object member names are case-sensitive. $.Store does not match store, and whitespace outside a quoted property name is syntax rather than part of the key.
Use bracket notation for awkward property names
Dot notation works for simple names. Bracket notation with a quoted string is needed when a key contains a dot, space, hyphen or another character the dot grammar treats specially.
{
"user.name": "Ada",
"display name": "Ada L",
"items": {"0": "object key, not array index"}
}
$['user.name']
$['display name']
$.items['0']$.user.name selects member name inside object user; it does not select the literal key user.name. This is a common silent no-match when data comes from flattened configuration or analytics events.
Quote escaping follows the JSONPath implementation's grammar. When an expression is itself inside JavaScript, JSON or a shell command, the host format adds another escape layer. Inspect the exact path string received by the evaluator.
Select array indexes and slices
A numeric bracket selects an array element, with zero as the first index. Thus $.store.book[0].title selects A. An out-of-range index normally produces no match rather than a JSON null value.
$.store.book[0].title -> "A"
$.store.book[1].price -> 12.50
$.store.book[99] -> no match
# Common slice form: start included, end excluded
$.store.book[0:2]Many implementations support Python-like slices [start:end:step], but details such as negative indexes are not universal. Check your engine before relying on [-1] for the last element.
An object key containing digits is not an array index. The current node's type determines meaning: [0] addresses an array position, while ['0'] addresses a named object member.
Use wildcards for all immediate children
The wildcard * selects every member value of an object or every element of an array at one level. $.store.book[*].title returns titles from each book element.
$.store.book[*].title
# ["A", "B"]
$.store.*
# every immediate value under the store object
$[*]
# every immediate child when the root is an array or objectWildcard result order for arrays follows array order. JSON object members are conceptually unordered, so do not use wildcard object order as a business guarantee even if one parser preserves source insertion order.
A wildcard does not recurse. If nested objects can contain the desired name at arbitrary depths, recursive descent may find them, but it also broadens the result set and work performed.
Understand recursive descent
The .. operator searches descendants rather than only direct children. $..price finds member values named price anywhere below the root. It is concise for exploration but can select unrelated fields that happen to share a name.
$..price
# all descendant members named price
$..book[*].title
# titles under every descendant member named book
$.store.book[*].price
# narrower and more predictable when the structure is knownPrefer an explicit path in application logic when the schema is stable. Recursive descent can become slower on large documents and may silently begin returning extra data when a new nested object introduces the same key.
Duplicate object member names in raw JSON are another trap. JSONPath operates on the parsed model, and many parsers retain only the last duplicate. Reject duplicate keys before querying when preserving source distinctions matters.
Filter array elements by a condition
A filter commonly uses [?(expression)], with @ referring to the candidate element. $.store.book[?(@.price < 10)].title selects titles of books whose numeric price is below ten.
$.store.book[?(@.price < 10)].title
# ["A"]
$.store.book[?(@.title == 'B')]
# the book object whose title equals BFilter syntax is the least portable part of JSONPath. Equality operators, regular expressions, boolean composition, existence tests and functions differ across libraries. Verify against your engine rather than assuming syntax copied from another tester will work.
Type comparisons matter. JSON number 10 and JSON string "10" are different values, though some implementations coerce them. Normalise source data or use explicit type-aware conditions when silent coercion could select the wrong records.
Debug no match, null and result shape
No match is not the same as matching a property whose value is JSON null. Libraries represent these differently: an empty list versus a list containing null, an undefined sentinel, or an exception in a single-value API.
{"present": null, "items": []}
$.present -> one match whose value is null
$.missing -> no matches
$.items[*] -> no matches because the array is emptyBuild a failing expression one segment at a time. Test $, then $.store, then $.store.book, inspecting the type at each step. Most failures are a wrong case, an array treated as an object, or a dotted key that needed bracket notation.
For production use, fix the JSONPath engine and version, define whether the API expects one or many results, and test representative missing and null cases. A query that works in an online tester is a useful prototype, not proof of cross-library portability.
Frequently asked questions
What does $ mean in JSONPath?
$ is the root of the JSON document. Paths such as $.store.book begin there and select successive child members.
What is the difference between dot and bracket notation?
Dot notation is concise for simple member names. Bracket notation with a quoted key is required for names containing dots, spaces, hyphens or other syntax characters, such as $['user.name'].
How do I select every item in a JSON array?
Use an array wildcard, for example $.items[*]. Add another child selector such as $.items[*].name to return one member from every selected element.
How do JSONPath filters work?
A common form is [?()], with @ representing each candidate array element—for example $.items[?(@.price < 10)]. Operators and functions vary significantly between engines, so test with the production implementation.
What does recursive descent do in JSONPath?
.. searches descendants at any depth, so $..price finds all members named price. Prefer a direct path when the schema is known because recursion may become slower and select unrelated future fields.
Why does my JSONPath return no result?
Check member-name case, the type at every segment, array indexes and keys containing dots. Build the path one segment at a time, and distinguish an empty match set from a matched property whose value is JSON null.
Ready to try it?
Open the free browser-based JSON path tester and apply what you just read — no sign-up, runs locally.
Open the JSON path tester tool