Skip to content

🔎 JSONPath Tester

Evaluate JSONPath queries (e.g. $.store.book[*].author) against JSON data in real time. Filters, recursive descent, and wildcards supported.

100% Free No signup Browser-only 5 languages Dark mode

🔒 About Privacy


    
📚 JSONPath Syntax Help
$ — Root object
@ — Current node (in filter)
.field / ['field'] — Child member access
.. — Recursive descent (any depth)
* — Wildcard (all elements)
[index] — Array index
[start:end:step] — Array slice
[a,b,c] — Multiple indexes / fields
[?(@.price < 10)] — Filter expression
[?(@.tags)] — Field existence

📖 Where people get stuck

Evaluates JSONPath queries against JSON as you type, showing the matched values and how many there are, with recursive descent, wildcards, slices and filter expressions. Everything runs in the browser. JSONPath had no formal specification until RFC 9535 in 2024for the seventeen years before that, every implementation interpreted a 2007 article in its own way, which is why the same expression returns different results in different implementations.

Case What happens What to do
The same expression behaves differently per implementation Three areas carried most of the ambiguity: combining recursive descent with an index — is $..book[0] the first element of each array, or the first of all the books gathered together; whether the result is always an array or a bare value when there is only one; and what happens when a filter expression references a field that does not exist. Because the answer changes the moment you switch implementations, it surfaces as an upgrade suddenly breaking something — and since the expression did not change, the cause is not obvious. Choose a library that states RFC 9535 conformance — anything published from 2024 onward says so. For existing code, the only recourse is to check the actual behaviour in your library documentation. Practically, avoiding the constructions where ambiguity lives is the surest route: do not put an index directly after a recursive descent $.., always take the result as an array and index it in your own code, and pair filters with an existence check, as in ?(@.price && @.price < 10). Keep to those three and implementation differences barely reach youthe more clever the expression, the less portable it becomes.
The filter expression does not work A numeric comparison such as ?(@.price < 10) works in most implementations, but string comparison runs into the question of quote style: there are implementations that reject the single quotes in ?(@.category == 'fiction') and others that reject double quotes. RFC 9535 permits both, but older implementations often accept only one. Worse, some fail depending on whether there is whitespace around the operator, and some require = rather than == — and none of them raise an error; they simply return nothing. Build the query in stages rather than writing it all at once — look at $, then $.store, then $.store.book, then $.store.book[*], and only then the filter, and you will see exactly which step went to zero. This is the fastest way to debug any query language of this kind, because a result of zero on its own cannot distinguish a typo from missing data from a syntax the parser did not accept. Once you know the filter is at fault, try swapping the quote style, removing the whitespace around the operator, and == against =, in that order. And when the filter you need becomes complicated, writing it in code instead is more readable and can be tested.
Confusing JSONPath with JMESPath and jq The names and the appearance are similar, but these are three different languages with almost no syntactic compatibility. The AWS CLI --query is JMESPathReservations[].Instances[].InstanceId, with no $. kubectl -o jsonpath is a Kubernetes-specific dialect, wrapped in {}, allowing $ to be omitted and adding its own range construct. jq is an entirely separate query language, with pipes, variables and function definitions. This is behind many cases of an expression found online not working when pasted in, and discovering that the JSONPath article you were reading was actually about JMESPath is a common experience. Confirm which language you are looking at before you use it. Telling them apart is easy: starting with $ means JSONPath; no $ but [] and | means JMESPath; a run of .field, select() and pipes means jq. One more thing: JSONPath is read-only — it cannot modify values, restructure, or aggregate. If you want to transform what you extracted, use jq, which is a transformation language and comes with map, group_by and reduce. As a rough guide: JSONPath to pull one value out of a config file, jq to reshape JSON in a shell, JMESPath when working with AWS — and where you have a choice, matching whatever is already used in that environment causes the least friction.

Before reaching for JSONPath, ask whether you need it. When you are handling JSON inside a program, parsing it and walking the native structure gives you types, points at the location of an error, and can be testeddata.store.book.filter(b => b.price < 10) is plainly more readable than $.store.book[?(@.price<10)] buried in a string, and your editor can complete it. JSONPath earns its place when the query is decided at runtime: extraction rules given in a configuration file, mappings defined by a user, saved log search conditions — situations where the query is data. In those cases, be careful with queries that arrive from outside: JSONPath itself executes no code, but a recursive descent $.. run against a large JSON document will consume your CPU and memory. Cap both the size of the input and the complexity of the expression.

📖 How to Use

  1. 1
    Paste JSON
    Paste the JSON document on the left. The Sample button loads example data.
  2. 2
    Enter a query
    Type a JSONPath expression starting with $. Results update live. Filters and wildcards are supported.
  3. 3
    Inspect the result
    Matching values are pretty-printed on the right with the match count and any errors.

❓ Frequently Asked Questions

What is JSONPath?
A query language for JSON, analogous to XPath for XML. It uses $ as the root and supports dot/bracket notation and filter expressions.
How do I write filters like [?(@.price < 10)]?
@ refers to the current node. Comparison and logical operators (==, !=, <, <=, >, >=, &&, ||) are supported. Wrap string literals in single quotes.
When should I use the recursive descent (..)?
Use it to find all matches at any depth. $..author collects the author field wherever it appears in the document.
🐛 Found a bug or issue with this tool?

Free to use, no signup. Even just the steps to reproduce are helpful. Reports go directly to the operator and help us fix issues.

* Browser info (UA / screen / language / URL) is sent automatically to help reproduce the issue