Test a JSONPath query against your JSON

Paste JSON and a JSONPath query to see the matched values and their normalized paths. Follows RFC 9535. Nothing is uploaded.

How it works

  1. Paste your JSON in the first box
  2. Type a JSONPath query that starts with $
  3. Read the matched values and their paths

How the JSONPath tester works

A JSONPath query starts at the root, written $, and walks down the JSON one step at a time; every value it ends on is a match. This page evaluates the query with its own implementation of the core of RFC 9535, the standard for JSONPath, and lists the matched values as a JSON array next to the normalized path of each match. Each step is a segment: .name or ['name'] picks a member, [0] or [-1] picks a list item from the front or the back, [1:4] and [::2] take slices with a start, an end and a step, * takes everything one level down, and .. looks through every level below. Several selectors in one bracket, such as [0,2], are joined in the order you write them. The page opens with a sample so you can see a result before you paste anything.

A worked example with a filter

Take a store with four books priced 8.95, 12.99, 8.99 and 22.99, where the first and third carry the tag x. The query $.store.book[?@.price < 10 && @.tag == 'x'].title keeps the books that cost under 10 and have the tag x, then takes their titles. It matches two values and the paths $['store']['book'][0]['title'] and $['store']['book'][2]['title']. The query $..price finds every price at any depth: the four book prices and a bicycle price, five matches. $.store.book[-1] is the last book, and $.store.book[0:4:2] is books 0 and 2. In a filter, @ means the item being tested and $ still means the root, so $.xs[?@ < $.max] compares each item with a value elsewhere in the document.

Filters and functions

A filter is ? followed by a test. Tests compare with ==, !=, <, <=, > and >=, combine with && and ||, negate with ! and group with parentheses. A bare query such as ?@.isbn is an existence test: it is true when the member is present, even if its value is null. Comparing a number with a string is never equal and never smaller, so 30 and "30" differ. Five functions are built in. length(@) is the number of characters in a string, items in a list or members in an object. count(@.*) is the number of nodes a query finds. value(@.t[*]) is the single value a query finds. match(@, 'a.*e') needs the whole string to fit the pattern, and search(@, 'apple') needs only a part of it to.

Regular expressions and safety

The patterns for match and search use the JavaScript engine of your browser, with the u flag. A pattern that repeats a group that already repeats, such as (a+)+, is refused with a message, because it can take a very long time to run. Lookahead, lookbehind and backreferences are refused too, since the JSONPath regular expression format has none of them. A pattern that is not valid matches nothing, and a note says so. A string longer than 10,000 characters is not tested, and the query stops with a message.

Limits and what is not supported

The JSON must be strict: double quotes, no comments, no trailing commas, up to 500,000 characters and 500 levels deep. Numbers are read as JavaScript numbers, so an integer beyond 9,007,199,254,740,991 loses digits. Members of an object are walked in the order JavaScript keeps them, which puts keys that look like whole numbers first. A query stops with a message after it has looked at 1,000,000 nodes. Script expressions from older libraries, such as [(@.length-1)], are not part of RFC 9535 and are rejected; use [-1] for the last item. Everything runs in this tab.

Frequently asked questions

How do I test a JSONPath expression online?

Paste the JSON into the first box and the query into the second. The page lists every matched value and its path at once, for example $.store.book[0].title gives one title and the path $['store']['book'][0]['title']. A query that does not start with $ is reported with the position of the problem.

How do I filter by a value in JSONPath?

Use a filter in brackets: $.store.book[?@.price < 10] keeps the books priced under 10. Join tests with && and ||, as in ?@.price < 10 && @.tag == 'x'. Strings go in single or double quotes, and the parentheses of older styles such as ?(@.price<10) still work.

What does .. mean in JSONPath?

It is the descendant step: it looks at the current value and everything nested below it at any depth. $..price finds every member named price anywhere in the document, and $..[0] takes the first item of every list, including lists inside lists.

Why does my JSONPath work in another tool but not here?

This page follows RFC 9535. Older libraries accept script expressions like [(@.length-1)], and implementations differ on edge cases because JSONPath had no standard before RFC 9535. Use [-1] for the last item and write filters as tests such as ?@.price > 5.

How do I get the last item of a list in JSONPath?

Use a negative index: $.store.book[-1] is the last book and [-2] is the one before it. A slice such as [-2:] takes the last two. An index beyond the list, like [9] on a list of four, matches nothing and is not an error.

Is my JSON uploaded?

No. The text is processed in your browser and not uploaded. Your JSON and your query are never saved; only the Compact output setting is kept on this device.