Overview
Introduction
Once JSON gets deeply nested, pulling out exactly the values you need by hand becomes tedious. JSONPath gives you a compact query language for that, similar in spirit to XPath for XML, and this tool lets you write and test expressions against real data instantly.
It exists because writing a JSONPath expression against a document you can't see is mostly guesswork: you write $.store.book[?(@.price < 10)], run it somewhere in application code, and only find out it's wrong when the result is empty or crashes. Testing it here first turns that trial and error into an immediate feedback loop, with the actual matches and their resolved paths shown as you type.
What Is JSONPath Tester?
A JSONPath tester evaluates a JSONPath query expression against a JSON document and returns every value that matches, along with the exact resolved path to each match.
It supports the common subset of the language that shows up in real-world use: the dollar root ($), dot and bracket member access, wildcards (* and [*]), recursive descent (..key), array indices, comma lists, slices, and filter expressions with a single comparison, like [?(@.price < 10)].
Because filter expressions are evaluated by a small, purpose-built comparison engine rather than by running arbitrary JavaScript, evaluation is safe to perform directly on whatever you paste, and it happens entirely inside your browser: no document or expression is sent anywhere to compute a result.
How JSONPath Tester Works
The expression is parsed into a sequence of steps (member access, wildcards, array indices, slices, recursive descent, and filters), which are then applied one at a time against the parsed JSON, narrowing down from the root ($) to the final set of matches. Filter expressions like [?(@.price < 10)] are evaluated with a small, safe comparison engine rather than executing arbitrary code.
Because each step operates on the current match set from the previous step, an expression like $.store.book[?(@.price < 10)].title reads left to right: start at the root, descend to store.book, keep only array items whose price is under 10, then pull the title from what's left. The evaluator tracks the resolved path alongside each value the entire way, which is why the output can show you $.store.book[2].title rather than just the string it contains.
Wildcards and recursive descent look similar but aren't interchangeable: [*] and ..* both mean 'every value,' but only the bracket and double-dot forms are recognized; a bare dot-star ($.*) is parsed as an attempted, invalid member access instead. Recursive filters ($..[?(...)]) only test items inside arrays encountered while descending; they don't apply a filter condition to a bare object's own properties, since a filter step is defined to iterate over array elements.
When To Use JSONPath Tester
Use it to prototype an extraction query before hardcoding it into application code, to explore an unfamiliar API response and find where a specific value lives, or to debug why a JSONPath expression used in a config (like an OpenAPI extension or a log processor rule) isn't matching what you expect.
It's particularly useful when the JSON structure itself is the unknown: instead of manually expanding a large nested object in a debugger to find where a field lives, a recursive-descent query like $..price surfaces every matching value across the whole document at once, along with exactly where each one is.
Often used alongside JSON Formatter & Beautifier and JSON Validator.
Features
Advantages
- Shows the exact resolved path for every match, not just the value.
- Supports the most commonly used JSONPath features: wildcards, recursive descent, slices, and filters.
- Safe filter evaluation without executing arbitrary JavaScript.
- Instant feedback lets you iterate on an expression quickly.
Limitations
- Filter expressions support a single comparison (property, operator, value) rather than compound boolean logic (&&, ||).
- Script expressions and function extensions from advanced JSONPath implementations are not supported.
- Property names in filters are limited to a single level (@.key), not deeper paths like @.a.b.
JSONPath vs. Manual Property Access
| JSONPath (this tool) | Manual code (obj.a.b[0]) | |
|---|---|---|
| Works without knowing the exact structure | Yes, with wildcards and recursive descent | No, requires exact property names |
| Supports filtering by a condition | Yes | Only with extra written logic |
| Requires writing and running code | No | Yes |
| Best for | Exploring and prototyping queries | Production code once the path is known |
Examples
Best Practices & Notes
Best Practices
- Build complex expressions incrementally: start with $.store and add steps one at a time to see how the match set narrows.
- Use recursive descent (..) sparingly on very large documents, since it searches every level of the tree.
- Quote string values in filters (@.status == 'active') to avoid them being parsed as identifiers.
- Use [*] or ..* for wildcards, not a bare .*; the dot form isn't parsed as a wildcard by this evaluator and errors instead of matching everything.
- Once you've identified where a value lives, replace $.. with a specific dotted path in production code. A targeted path is faster and won't accidentally pick up an unrelated same-named key elsewhere in the document.
- Remember that a recursive filter like $..[?(...)] only inspects arrays it finds during descent, not bare object properties with the same field; query for the object directly if you need to test a condition on a single nested object.
Developer Notes
The evaluator returns both value and path for every match so results can be copied directly into code that reads a specific location, such as lodash's get() or a JSON Patch path. Filter expressions are evaluated with a small, purpose-built comparison engine, not JavaScript's eval() or Function(), so a filter can only perform one of the six supported comparisons against a literal (number, boolean, null, or quoted string). There's no way for a filter expression to run arbitrary code, which is what makes it safe to evaluate directly in the browser against whatever you paste. Negative array indices ([-1]) are resolved against the array's length at match time, but the path shown in the result preserves the original negative index you wrote (e.g. $.items[-1]) rather than rewriting it to the resolved positive index, so the displayed path always echoes your expression's own indexing.
JSONPath Tester Use Cases
- Extracting a specific nested value from a large API response
- Prototyping a JSONPath expression before using it in a log processing rule or API gateway config
- Exploring an unfamiliar JSON structure interactively
- Debugging why an existing JSONPath query isn't matching expected data
- Confirming the exact resolved path to pass to a downstream function like lodash's get() or a JSON Patch operation, instead of guessing at index numbers by hand
- Auditing a large config or payload for every occurrence of a particular field name before a refactor, using recursive descent to find every location it appears
Common Mistakes
- Forgetting to quote string values inside filter expressions.
- Expecting compound filters with && or || to work, when only a single comparison per filter is supported.
- Confusing recursive descent (..) with a typo of single-dot access, leading to unexpectedly broad matches.
- Writing $.* expecting a wildcard, when only [*] and ..* are recognized as wildcard syntax here.
- Assuming a recursive filter ($..[?(...)]) will match a bare object with the filtered property, when it only tests items inside arrays encountered during the descent.
- Treating an empty match list as an error; a valid expression that matches nothing returns a successful result with zero matches, not a failure.
Tips
- If an expression returns too many matches, add a more specific filter or index instead of relying on wildcards.
- Copy the resolved path from a match and reuse it as a plain member-access expression once you've found what you need.
- When porting a JSONPath expression from another library, check dot-wildcards (.*) and compound filters (&&/||) first, since those are the two most common features other implementations support that this evaluator doesn't.
- Start from $ and add one step at a time rather than pasting a long expression at once, so you can see exactly which step first produces an empty or unexpected match set.