JSON Path Tester
Paste JSON and a JSONPath expression to see exactly which values it matches, live as you type.
About the JSON Path Tester
JSONPath is a small query language for pulling values out of a JSON document without writing a loop yourself. This tester parses your expression into tokens first (root, property names, array indexes, wildcards, recursive descent), then walks your parsed JSON one token at a time, so $.store.book[*].author and $..price behave the way they would in a real JSONPath library rather than being approximated with a single regular expression. Recursive descent (..) checks every nested object and array at any depth, not just the top level, and negative array indexes like [-1] count back from the end of the array.
Why the evaluator works on a list of matches, not a single value
The evaluator starts with current = [root], a list containing just the root document, and every subsequent token transforms that list into a new list rather than tracking a single "current position." This is exactly what makes chaining a wildcard or recursive descent with further path segments work correctly without any special-casing: after evaluating [*] on an array of three books, current becomes a list of all three book objects, and the next token, .author, simply runs against every item in that list, collecting the author field from each one into the next list. A path like $.store.book[*].author naturally fans out and back in through this list-of-matches model, exactly the way a real JSONPath implementation handles it.
Two different recursive walkers for two different jobs
Recursive descent has two forms in this tester, and they're implemented as separate functions because they do genuinely different work. $..price needs to find every value under a key specifically named "price" at any depth, so collectRecursive walks every array and object, checking each object's own keys for a name match. $..* instead needs to collect every value at every depth regardless of its key name, so collectRecursiveWildcard pushes every single value it encounters while descending, with no name filter at all. Both functions recurse identically through arrays and objects, they just differ in what qualifies a value for inclusion in the results.
Why array property access is deliberately restricted
The property-matching logic explicitly checks that a value is a plain object and specifically not an array before treating a dot-notation property name as valid against it. That means something like $.store.book.author (using dot access directly on the array) won't match anything, arrays are only navigable through [*], a numeric index like [0], or recursive descent, never through a bare property name. This mirrors how real JSONPath treats arrays and objects as structurally distinct, a named property lookup is an object operation, not something that applies to a list.
Why the tool uses hasOwnProperty rather than a looser existence check
When matching a property name against an object, the evaluator specifically checks Object.prototype.hasOwnProperty.call(value, name) rather than a looser check like name in value. This guarantees only the object's actual, own JSON-sourced keys count as matches, never something inherited from JavaScript's built-in Object.prototype (like toString or hasOwnProperty itself). Without that specific check, a path expression could theoretically "match" a JavaScript-internal property that was never part of your actual JSON data at all.
Three separate error stages, each labeled for what actually broke
A failed query here can go wrong in three genuinely different places: your JSON might not be valid JSON at all, your JSONPath expression might have invalid syntax, or evaluation might hit something structurally unexpected while walking the parsed data. This tool catches and labels each stage separately, "Invalid JSON," "Invalid JSONPath," or "Evaluation error," rather than collapsing every possible failure into one generic error message, so you can tell at a glance whether the problem is with your data, your query syntax, or something in between.
Frequently Asked Questions
How does chaining a wildcard with another property, like [*].author, actually work?
The evaluator tracks a list of current matches rather than one value. After [*] runs, the list becomes every item in the array; the next token then runs against every item in that list independently, collecting results into a new list. This is what lets wildcards and further path segments chain together naturally.
What's the difference between $..price and $..*?
$..price searches every level of the JSON for values under a key specifically named "price". $..* has no name filter at all, it collects every single value at every depth regardless of its key. They're implemented as two separate recursive functions because they select values on different criteria.
Why doesn't $.store.book.author match anything if book is an array?
Dot-notation property access is deliberately restricted to plain objects and explicitly excludes arrays. Arrays can only be navigated with [*], a numeric index like [0], or recursive descent, never through a bare property name, matching how real JSONPath treats arrays and objects as structurally distinct.
Could a JSONPath expression accidentally match a built-in JavaScript property?
No, property matching specifically uses hasOwnProperty, which only recognizes an object's own actual keys from your JSON data. This prevents accidentally matching something inherited from JavaScript's built-in Object.prototype, like toString, that was never part of your original data.
How do negative array indexes like [-1] work?
A negative index is converted to length + index, so -1 on a 3-item array becomes index 2, the last item. If the resulting index still falls outside the array's actual bounds, it simply produces no match rather than throwing an error or wrapping incorrectly.
How can I tell whether a failed query is a JSON problem or a path syntax problem?
Errors are labeled by which stage failed: "Invalid JSON" means your data itself doesn't parse, "Invalid JSONPath" means the expression's syntax is wrong, and "Evaluation error" means something unexpected happened while walking the parsed data. Each is reported separately rather than one generic error message.