JSONPath tester

Run RFC 9535 JSONPath queries on JSON and see every match with its path.

RFC 9535 syntax, for example $..book[[email protected] < 10].title

Examples

2 matches

  1. $['store']['book'][0]['title']
    "Sayings of the Century"
  2. $['store']['book'][2]['title']
    "Moby Dick"

What this tool does

Paste a JSON document, type a JSONPath query, and every match appears as you type, each with its normalized path (such as $['store']['book'][2]['title']) and its value. You can copy all matched values as a JSON array, or all paths. The tool follows RFC 9535, the JSONPath standard the IETF published in February 2024, so a query that works here is written the way current libraries implementing the standard expect. Syntax errors show the column and a caret under the problem. Nothing is uploaded, and queries are evaluated by a parser written for this tool, not by running code.

The syntax in brief

  • $ is the root of the document; @ is the current item inside a filter.
  • .name or ['name'] selects a member; use brackets for names with spaces or symbols: $['first name'].
  • [0], [-1] select array elements from the start or the end; [0,2] selects several.
  • [start:end:step] is a slice, as in Python: [:2] is the first two, [::-1] is the array reversed.
  • * selects all members or elements; .. searches all descendants: $..price finds every price at any depth.
  • [?filter] keeps items for which the filter is true: $..book[[email protected] < 10], $..book[[email protected]] (has an isbn), [[email protected] == 1 && [email protected]].

Functions: length(@.name) counts characters, elements or members; count(@.tags[*]) counts query results; match(@.code, '[A-Z]{3}') tests a whole string against a regular expression, search() looks for it anywhere; value(@..id) turns a single-result query into a value.

Worked examples on the bookstore sample

The sample is the document from RFC 9535 itself, so results can be checked against the standard. $.store.book[*].author returns the four authors. $..book[[email protected] < 10].title returns "Sayings of the Century" and "Moby Dick", with the paths $['store']['book'][0]['title'] and $['store']['book'][2]['title']. $.store..price returns 8.95, 12.99, 8.99, 22.99 and 399: the book prices first, then the bicycle's, because descendants are visited depth first in document order. $..* returns 27 values: every member and array element in the document.

Rules that surprise people

  • Comparisons need a single value. @.* == 1 is an error, because @.* can return many values; RFC 9535 rejects it instead of guessing. The same goes for length(@.*).
  • Missing equals missing. If neither side of == exists, the comparison is true: $.a[[email protected] == $.x] keeps every item that has no b when $.x does not exist either.
  • Types do not convert. 13 == '13' is false, and < only compares numbers with numbers and strings with strings.
  • match() is anchored, search() is not. match(@.tz, 'Europe/.*') must match the whole string.
  • Results can repeat. $[0,0] returns the first element twice; the standard keeps duplicates.

Older JSONPath dialects (Goessner's 2007 article, Jayway for Java, jsonpath-plus) differ in details such as script expressions (@.length-1) and filter syntax; this tool implements the standard only. The article JSONPath vs jq vs JavaScript filters compares the three approaches. To tidy the input, use the JSON formatter; to get TypeScript types for it, JSON to TypeScript.

Frequently asked questions

Which JSONPath version does this follow?

RFC 9535, the IETF standard published in February 2024. Older dialects such as Jayway's (Java) or jsonpath-plus accept some extra syntax, like script expressions, that the standard dropped, and differ in a few results.

Why is @.* == 1 an error?

Comparisons in RFC 9535 accept only queries that can return at most one value (names and indexes, no wildcards, slices, filters or ..). Use a filter on the items instead, such as [?@ == 1] one level down.

What is a normalized path?

A canonical way to write where a value is: $ followed by ['name'] for each member and [n] for each array index, such as $['store']['book'][0]. It is unambiguous, so it can be used as an identifier for the match.

How do I filter by a string pattern?

Use match() for the whole string or search() for any part of it: $..book[?search(@.title, 'Lord')]. The patterns are regular expressions in the I-Regexp format (RFC 9485), a portable subset of the usual syntax.

Is my JSON sent anywhere?

No. Parsing and evaluation happen in your browser.