A JSONPath tester that follows RFC 9535
The JSONPath Tester runs a JSONPath query against your JSON as you type and lists every match with its normalized path — the exact location, such as $['store']['book'][0]['title'] — next to the value it found. Switch to In document to see the matches highlighted inside the formatted JSON, or click any value there to get the path that selects it.
JSONPath began with Stefan Goessner’s 2007 article and grew into many dialects; in February 2024 the IETF standardised it as RFC 9535. This tester is our own implementation of that standard (no third-party library), covering filters, recursive descent, slices, unions and the five standard functions. It passes all 706 cases of the JSONPath Compliance Test Suite (October 2026), including the queries that must be rejected.
Your JSON never leaves the browser: parsing and querying run locally, so API responses with tokens or customer data are safe to paste.
How to use the JSONPath Tester
- Paste JSON into JSON document, drop a
.jsonfile on it or press Load file. The bookstore example from RFC 9535 is loaded so you can start straight away. - Type a query that starts with
$in JSONPath query, or pick one from Try an example query. Open the Syntax cheat sheet whenever you need a reminder. - Read the Matches list of normalized paths and values. Click a path to copy it.
- Press the locate button on a match, or choose In document, to see every match highlighted. Click any value to show its path, then Copy path or Use as query.
- Open Output to copy or download the results as a JSON array of values, a list of normalized paths or a list of JSON Pointers.
JSONPath Tester features
Standard behaviour
Selectors, filters, comparisons and functions behave exactly as RFC 9535 describes, including the rules for missing members and type-strict equality.
Normalized paths and JSON Pointers
Every match comes with its RFC 9535 normalized path and, in Output, its RFC 6901 JSON Pointer (/store/book/0/title) for use in JSON Patch or code.
Highlighting and click-to-path
Matches are highlighted in a coloured view of the document, and clicking a value tells you how to reach it.
Errors with a column number
Invalid queries are rejected with the column, a caret and a plain reason — for example “use == to test equality, not =”, or that [(@.length-1)] belongs to an older dialect.
I-Regexp for match() and search()
Patterns follow RFC 9485 (I-Regexp) and are translated for the browser’s regular-expression engine; a pattern that is not valid I-Regexp simply matches nothing, as the standard requires.
Large files
Multi-megabyte documents are queried in a fraction of a second; above 40,000 values the highlighted view switches off.
Worked examples with the bookstore document
Results for the sample document (Figure 1 of RFC 9535), which Sample loads:
| Query | Result |
|---|---|
$.store.book[*].author | 4 matches: "Nigel Rees", "Evelyn Waugh", "Herman Melville", "J. R. R. Tolkien" |
$..book[2].title | "Moby Dick" at $['store']['book'][2]['title'] |
$..book[-1].title | "The Lord of the Rings" |
$.store..price | 8.95, 12.99, 8.99, 22.99, 399 |
$..book[?@.isbn].title | "Moby Dick", "The Lord of the Rings" |
$..book[?@.price < 10].title | "Sayings of the Century", "Moby Dick" |
$..book[?@.category == 'fiction' && @.price < 20].title | "Sword of Honour", "Moby Dick" |
$..book[?length(@.title) > 15].title | "Sayings of the Century", "The Lord of the Rings" ("Sword of Honour" has exactly 15 characters) |
$..* | 27 nodes: every member value and array element |
How filters and functions behave
- A filter such as
[?@.price < 10]keeps the children of an object or array for which the test is true; parentheses around the test are optional. @.isbnon its own is an existence test: it is true when the member exists, even if its value isnullorfalse.- Comparisons are type-strict:
13 == '13'is false.<and>only order numbers with numbers and strings with strings; anything else is false. - A missing member is “Nothing”. Two missing members compare equal, so
$.a[?@.b == $.x]keeps every element that has nob. - Only singular queries (names and indexes, no wildcard or
..) can be compared or passed tolength(),match()orsearch();count()andvalue()take any query. match()needs the whole string to match;search()is satisfied by any substring. To use a regex escape inside a quoted literal, double the backslash:search(@.author, 'R\\.').
Differences from older JSONPath dialects
Libraries that predate the RFC, such as Goessner’s original and Jayway JsonPath for Java, accept syntax that RFC 9535 does not:
| Older dialects | RFC 9535 (this tester) |
|---|---|
Script expressions such as $..book[(@.length-1)] | Not supported — use $..book[-1] |
@.length means the array length | @.length selects a member named “length”; use length(@) |
Jayway regex operator =~ /re/i | match() or search() with an I-Regexp, no flags |
Jayway operators in, nin, size, empty, anyof | Not defined; combine comparisons with || and && |
Path functions like .min(), .sum(), .keys() | Only length, count, match, search and value, inside filters |
| A single value returned for definite paths (Jayway) | Always a list of nodes, possibly empty |
| Filters evaluated as JavaScript | A fixed, safe expression grammar |
JSONPath Tester FAQ
What is JSONPath?
JSONPath is a query language for JSON, much like XPath for XML. A query starts at the root $ and steps in with names, indexes, wildcards, slices and filters. A JSONPath tester shows exactly which nodes a query selects before you use it in code or an API gateway.
Why does a query from Jayway or another library fail here?
Many libraries predate RFC 9535 and accept extras such as =~ regexes, .length() or script expressions. The error message names the problem and the table above gives the standard replacement.
What is a normalized path?
It is the unique, canonical way RFC 9535 writes the location of one node: bracket notation with single-quoted names and plain indexes, like $['store']['book'][2]. A normalized path is itself a valid query that selects exactly that node.
What is the difference between match() and search()?
match(@.code, '[A-Z]{3}') is true only when the entire string is three capital letters. search(@.code, '[A-Z]{3}') is true when three capitals appear anywhere in it. Both use I-Regexp (RFC 9485), a portable subset of regular expressions; try patterns in the Regex Tester.Why do I get no matches?
Member names are case-sensitive, array indexes start at 0, and a filter only looks at the children of the node before it — $.store.book[?@.price < 10] filters books, but $.store[?@.price < 10] filters the store’s members. If the JSON itself is invalid, fix it first; the JSON Formatter shows the exact error.
Is my JSON uploaded anywhere?
No. The document and queries stay in your browser tab. Nothing is sent to a server, stored or logged.