Formatter Validator Minifier Escape / Unescape JSON ↔ String JSON ↔ YAML JSON → CSV NDJSON / JSON Lines JSON → Types JSON ↔ XML JSON Diff JSON Patch Canonicalize (RFC 8785) Schema Validator Schema Generator JSONPath Tester JWT Decoder JSON Errors Schemas More Tools
JSONPath queries · Live results · Goessner syntax

JSONPath Tester

Query JSON with JSONPath as standardised in RFC 9535 (IETF Standards Track, February 2024). Full filter expressions, the five built-in functions, and Normalized Paths for every match — verified against the official compliance test suite.

📄 JSON document
🎯 Matched results
Enter a JSONPath expression above

What is JSONPath?

JSONPath is a query language for JSON, analogous to XPath for XML. It lets you describe a path through a JSON document with a compact syntax: instead of writing nested loops and conditionals to extract specific values, you write a single path expression.

For example, given an API response with a list of users, $.users[*].email extracts every email address. $.users[?(@.role=="admin")].name extracts the names of admin users. $..price finds every "price" field anywhere in the document, no matter how deeply nested.

JSONPath was originally specified by Stefan Goessner in 2007 and has been implemented widely — in nearly every programming language, in jq (with adjusted syntax), in tools like Postman, and now in the IETF RFC 9535 standardization. Our tester implements the Goessner subset that all libraries agree on.

Complete JSONPath syntax reference

$ Root

The root of the JSON document. Every JSONPath starts with $.

.name Dot child

Access an object property by name. $.user.name returns the name field of the user object.

['name'] Bracket child

Access by name with brackets — needed for keys with special characters: $['user-name'].

[*] Wildcard

All elements of an array or all values of an object. $.users[*] returns every user.

.. Recursive descent

Match at any depth. $..price finds every "price" property anywhere in the tree.

[2] Array index

0-based index into an array. $.users[0] returns the first user. Negative indexes count from the end.

[1:3] Slice

Range of indexes (like Python slices). $.users[0:3] returns the first three users.

[?()] Filter

Filter array elements by predicate. $.users[?(@.age > 18)] returns users older than 18.

[a,b] Union

Multiple keys at once. $['name','email'] returns both the name and email fields.

JSONPath examples in practice

Here are real-world JSONPath expressions for common tasks:

  • $.data.items[*].id — extract all item IDs from a paginated response
  • $..error — find every error message anywhere in a nested response
  • $.users[?(@.active==true)].email — emails of all active users
  • $.products[?(@.price > 100 && @.stock > 0)].name — names of in-stock products over $100
  • $.orders[-3:] — the last 3 orders
  • $.users[*].address.city — the city of every user
  • $..book[?(@.isbn)] — every book that has an ISBN field
  • $['key with spaces']['nested key'] — accessing keys with special characters

FAQ — Jsonpath Tester

Which JSONPath dialect does this tool use?
Goessner's JSONPath — the most widely supported variant, used by Jayway (the de-facto Java standard), Newtonsoft.Json in .NET, and most JavaScript libraries. RFC 9535 (the new IETF standard, finalized in 2024) is similar but stricter; we follow Goessner for maximum compatibility with existing tooling.
Is JSONPath the same as jq?
No, jq is a different language with its own syntax. jq is more powerful (it can transform, not just select) but more complex. JSONPath is a subset focused purely on selection. For simple extraction, JSONPath is easier; for transformation pipelines, jq is the right tool.
What's the difference between . and ..?
Single dot accesses a direct child. Double dot is recursive descent — it searches at every depth. $.a.b only finds b directly under a. $..b finds b anywhere in the tree.
Can JSONPath modify or transform data?
No — JSONPath is read-only. It returns the values that match a path; it doesn't change them. For modification, use a different tool: jq, JSONata, or a programming language with JSONPath bindings.
How are filter expressions evaluated?
Filters use @ to refer to the current array element. $.users[?(@.age > 18)] iterates over each user and tests whether their age field exceeds 18. Operators supported: ==, !=, <, <=, >, >=.
Does this support functions like length() or sum()?
Function extensions vary by JSONPath implementation and aren't part of Goessner's core spec. We don't support functions — keeping to the universally portable subset. For aggregations, extract the values with JSONPath first, then aggregate in your code.
Why does $.. return so many results?
Recursive descent matches at every depth. $.. alone matches every node in the document — including the root, every object, every array, every value. Almost always you want to chain a property after: $..name finds every "name" field.
How do I match a key that contains a dot or brackets?
Use bracket notation with quotes: $['key.with.dots'] instead of $.key.with.dots (which the parser would interpret as nested access).
Can I select by value instead of by key?
Indirectly, with filter expressions on parent context. $.users[?(@.role=="admin")] selects users whose role equals admin. There's no direct "find a value" — JSONPath always selects from a position in the tree.
How does negative indexing work?
Negative indexes count from the end of an array. [-1] is the last element, [-2] the second-to-last, and so on. For slices, [-3:] means "the last three elements".

703/703 on the official RFC 9535 test suite

JSONPath existed for twenty years as a blog post before it became a standard, and implementations drifted apart badly. RFC 9535 fixed the grammar and, importantly, the semantics. This tester is scored against the JSONPath Compliance Test Suite maintained by the working group:

Category Result
Evaluation — the query returns the right nodes 456 / 456
Rejection — invalid queries are refused 247 / 247

The second row matters as much as the first. RFC 9535 §2.1 requires a conforming implementation to reject a query that does not match the grammar rather than guess at it, so $[], $.., $[0,] and $[@.a] produce an error with a position, not a silently different answer.

Where RFC 9535 differs from older implementations

Comparisons are strictly typed

$[?@.a=="1"] matches the string "1" and not the number 1. Many pre-standard implementations coerced, which quietly returned extra rows.

Five built-in functions

length(), count(), value(), and match() / search() using I-Regexp (RFC 9485). Function arguments are type-checked at parse time, so a mistyped call is an error rather than a false result.

Normalized Paths

Every match is reported with its Normalized Path (§2.7) — the canonical, unambiguous location of that node, which you can feed back in as a query.

Specifications

Where to go next