FreeToGenerate.com

Runs a real RFC 9535 engine — all 703 compliance tests pass. Nothing is uploaded.

Try

Anything valid. The query runs against it as you type.

Results

2 nodes

[
  "Sayings of the Century",
  "Moby Dick"
]

Normalized paths

  • $['store']['book'][0]['title']
  • $['store']['book'][1]['title']

Every result also has a normalized path — the single unambiguous way to write a query selecting exactly that one node. The specification defines this form so two implementations can agree on what they matched, and it always uses bracket notation with single quotes.

Result order

Fixed. Every conforming implementation returns these nodes in this order.

Only two things make an order open, and the specification names both. Selecting members of an object is one, because JSON objects have no order — arrays, by contrast, always keep theirs. A segment carrying more than one selector is the other, and it also produces duplicates: a query like [0,0] selects the same node twice, and the specification explicitly calls an implementation that returns it once non-conforming.

Measured against the official test suite

tests passed
703/703
of them invalid queries
247
accept several orderings
9

RFC 9535 ships a compliance test suite, so how well an implementation works is a number rather than a claim. This engine passes all 703. A third of that corpus is queries that must be REJECTED, which is the part a permissive parser fails — accepting a malformed query is a failure even when no sensible answer existed.

Why the standard matters here

JSONPath circulated for two decades as a blog post with no specification. Implementations invented their own answers and disagreed on ordinary queries, which is why the same expression could return different things in different languages. RFC 9535 arrived in February 2024 and settles it: the phrase implementation-defined does not appear in it once.

The rule most older implementations get wrong is about types. A comparison may only involve a literal, a singular query — one that can select at most one node — or a function returning a value. So a query like $[?@.* == 1] is a syntax error rather than a comparison that quietly returns nothing. And a path selecting nothing yields a special value called Nothing, which equals only itself: two missing paths compare equal, while a missing path is neither less than nor equal to a number.

Built to RFC 9535, with regular expressions following RFC 9485. Nothing is uploaded — the query runs in this tab.

Also available in: Español · Português · Français · العربية

JSONPath Tester

Evaluate a JSONPath query against your JSON and see the matching nodes, their normalized paths, and whether the result order is fixed by the standard.

What is JSONPath?

JSONPath is a query language for JSON, in the way XPath is one for XML. An expression like $.store.book[?@.price < 10].title walks into a document and pulls out the parts you want — every book under ten, and only its title. It turns up in Kubernetes and kubectl, in CI configuration, in log pipelines, in API gateways and in a great many libraries that needed a way to say which bit of a payload they meant.

For most of its life it had no specification. It began as a blog post in 2007, everyone implemented it from that description, and the implementations quietly disagreed — the same query could return different results, in a different order, depending on which language you ran it in. There was no document to appeal to when two of them differed.

RFC 9535 changed that in February 2024. This tester runs a real implementation of that standard: paste a query and a document, and you get the matching nodes, the normalized path of each, and a statement about whether the order you are looking at is guaranteed.

How to use it

  1. Write a query. Start from the samples if you want — one filters by price, one gathers every price in the document, and two show what happens when the order is not fixed. Results update as you type.
  2. Paste your JSON. Any valid document. If it does not parse, the tool says so rather than pretending the query failed.
  3. Read the paths and the order note. Each result carries its normalized path — the one unambiguous way to address that node. Underneath, the tool says whether every conforming implementation would return these nodes in this order, or whether another one is free to differ.

What the standard settles, and the two things it does not

The useful news is how much RFC 9535 pins down. The phrase implementation-defined does not appear in it once. Descendant traversal order, slice semantics with negative steps, what a comparison does when one side selects nothing — all specified, all testable.

There are exactly two places where result order is genuinely open, and the specification names both rather than leaving you to discover them. The first is selecting members of an object: JSON objects have no order, so a wildcard over one may come back either way round. Arrays are not affected — their order is always preserved, which is the half people usually assume is at risk.

The second is a segment carrying more than one selector, like [0,0] or [*,*]. That produces each matching node once per selector — genuinely duplicated, not deduplicated — and the interleaving is not fixed. This one is worth knowing because the specification goes out of its way to say that implementations returning such a node only once do not conform. If you have relied on a library collapsing duplicates, that behaviour is not standard.

The rule most older implementations get wrong is about types. A comparison may only involve a literal, a singular query — one that can select at most one node — or a function returning a value. So $[?@.* == 1] is a syntax error, not a comparison that quietly matches nothing. And a path that selects nothing produces a special value called Nothing, which equals only itself: two missing paths compare equal, while a missing path is neither less than nor greater than a number. It follows, from the specification's own derivation of the operators, that two missing paths also compare less-than-or-equal.

How this engine was checked, and what that does not prove

RFC 9535 ships an official compliance test suite, which turns how well an implementation works into a number. There are 703 tests and this engine passes all of them. That figure is asserted in the build, so it cannot quietly rot.

A third of that corpus — 247 tests — consists of queries that must be rejected. That is the part a permissive parser fails, and it is a fair share of the work: the standard is strict about whitespace, about where a non-singular query may appear, and about which escapes are legal inside a quoted name. Accepting a malformed query counts as a failure even though no sensible answer existed.

A perfect score is not a proof of correctness, and this build is a good illustration. The specification defines only two comparison operators and derives the rest, so that a is less-than-or-equal-to b means a is less than b or a equals b. Because two Nothings compare equal, two Nothings must also compare less-than-or-equal. A hand-written version of that operator returned false instead — and the compliance suite scored 703 out of 703 with the bug present, because the corpus does not happen to cover it. It was caught by separate assertions derived from the specification's text rather than from its tests.

The limits worth stating: the tool parses your document with the browser's own JSON parser, so a number too large for a double is already rounded before the query sees it — the standard has a good deal to say about interoperable numbers, and none of it can rescue a value that was lost at parse time. Regular expressions inside match and search follow RFC 9485, which is a small subset without capture groups, lookahead or backreferences; a pattern using those is not a valid I-Regexp and the function is defined to return false rather than to error.

Why is it free?

The engine runs in your browser. Parsing a query and walking a document costs nothing on your own machine, so there is no server to pay for and no account to create.

Nothing you paste is uploaded, stored or logged. The JSON you are debugging is usually a real payload from a real system, and the reliable way to keep that private is never to receive it.