Running a JSONPath query
JSONPath is a small query language for JSON, in the same spirit as XPath for XML. A path starts at $ (the whole document) and steps down through keys and array positions, with wildcards, recursive search and filters for picking items by value. This tester runs one expression against the JSON you paste and returns every matching value as a JSON array.
There are two main flavours. The original syntax comes from Stefan Goessner's 2007 article. In 2024 the IETF standardised a stricter version as RFC 9535. This tool uses the jsonpath-plus library (version 11), which follows the original syntax and adds some extensions.
Sample data and verified results
{"orders": [
{"id": 101, "customer": "Lee", "total": 42.5, "items": [{"sku": "PEN", "qty": 3}, {"sku": "INK", "qty": 1}]},
{"id": 102, "customer": "Ruiz", "total": 310, "status": "refunded", "items": [{"sku": "DESK", "qty": 1}]},
{"id": 103, "customer": "Okafor", "total": 18.99, "items": []}
]}
| Expression | Result | What it does |
|---|---|---|
$.orders[*].id |
[101, 102, 103] |
Every order's id |
$..sku |
["PEN", "INK", "DESK"] |
Recursive descent: sku at any depth |
$.orders[0:2].id |
[101, 102] |
Slice: indexes 0 and 1 |
$.orders[-1:] |
the Okafor order | Last element via a slice |
$['orders'][0]['customer'] |
["Lee"] |
Bracket notation, handy for keys with spaces |
$.orders[?(@.total > 40)].customer |
["Lee", "Ruiz"] |
Filter on a value |
$.orders[?(@.status)].id |
[102] |
Filter on a key existing |
$.orders[?(@.total > 40 && @.id > 101)].id |
[102] |
Combined conditions |
$.orders[?(@.items.length == 0)].id |
[103] |
Array length inside a filter |
$.orders[*].items[*].qty |
[3, 1, 1] |
Nested wildcards |
$.orders[*]~ |
[0, 1, 2] |
Extension: return keys/indexes instead of values |
Steps
- Paste the JSON document into the first box. If it doesn't parse, you'll see "Enter valid JSON in the first field."; the JSON validator shows where it breaks.
- Type the expression into the second box, starting with
$. - Click Test. Matches appear as a two-space indented JSON array.
- "No matches found for that JSONPath expression." means the path is syntactically fine but selects nothing. Shorten it step by step until something matches, then add the next step back.
Differences from RFC 9535
If you're writing paths for a system that follows the RFC (some newer libraries and databases do), test the edge cases there too. These differences were confirmed with this tool:
| Expression | RFC 9535 | Here |
|---|---|---|
$.orders[-1] |
Last order | No match; use [-1:] |
$.orders[?@.total > 40] |
Filter without parentheses | No match; write ?(...) |
$.orders[?(length(@.items) == 0)] |
Function extension | Error: length is not defined |
$.orders[?(search(@.customer, "^O"))] |
Regex function | Error: search is not defined |
$.orders.length |
No match (not a member) | [3], read as an array property |
orders[0].id (no $) |
Invalid | Accepted, [101] |
The =~ regex operator found in some other implementations isn't supported either; it gives an "Invalid left-hand side in assignment" error.
Things to watch
Malformed paths are rejected before the query runs. The underlying library is lenient and would read an unfinished expression like $.orders[ as $.orders, so the tester checks the structure first: brackets and parentheses must pair up, quoted names must be closed, [] can't be empty, and the path can't end in . or contain .... $.orders[ gives "Invalid JSONPath expression: the "[" at character 9 is never closed with "]"." This check is structural only, so a well-formed path with a misspelled key still just finds no matches.
Results are values, not locations. You get the matched values, not their paths. To see where in the document a value sits, browse the data in the JSON/XML tree viewer.
Large numbers. The document is read with JSON.parse, so integers beyond 2^53 - 1 lose precision in the output, the same as anywhere else in JavaScript.
Putting results to work
A common use is pulling a clean array of records out of a nested API response before handing it to another tool. $.orders[*] turns the sample above into a flat list of order objects that the JSON to Excel converter can turn into a spreadsheet. If your data is XML, the XPath evaluator does the same job with XPath 1.0.
Last updated