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.