JSON Assertion Runner
Paste a JSON response and a small assertion list, then check values, types, ranges, counts, and regex matches locally in your browser.
About this tool
JSON Assertion Runner is a small contract-test runner for JSON payloads. Paste an API response, fixture, or event body, then write assertions with JSONPath selectors and simple operators. The output is a pass/fail report that names the failing rule, the matched location, and the actual value when a comparison fails.
Use it when a full test framework is too heavy but you still need repeatable checks: smoke tests for API samples, fixture validation before a demo, webhook payload checks, or QA notes that should be executable instead of prose.
Assertion syntax
The line DSL is one assertion per line:
$.status equals ok
$.user.id matches ^u-\d+$
$.items length 2
$.items[*] count 2
$.items[*].price gt 0
$.items[*].price lte 100
$.user.roles contains admin
$.user.name type string
$.optional not_exists
Blank lines and # comments are ignored. The same rules can be supplied as a JSON array of objects with path, op, and optional expected fields (plus an optional name that is echoed in the report) when you want to generate checks from another script.
Supported operators include exists, not_exists, equals, not_equals, type, gt, gte, lt, lte, range, contains, not_contains, matches, count, length, empty, and not_empty.
Worked example
Payload:
{"status":"ok","user":{"id":"u-42","roles":["admin","dev"]},"items":[{"sku":"A1","price":9.5},{"sku":"B2","price":250}]}
Assertions:
$.status equals ok
$.user.id matches ^u-\d+$
$.user.roles contains admin
$.items length 2
$.items[*].price gt 0
Report:
PASS — 5 of 5 assertions passed, 0 failed
PASS #1 $.status equals "ok"
PASS #2 $.user.id matches ^u-\d+$
PASS #3 $.user.roles contains "admin"
PASS #4 $.items length 2
PASS #5 $.items[*].price gt 0
Swap the last rule for $.items[*].price lte 100 and the run fails with the value that broke it:
FAIL — 4 of 5 assertions passed, 1 failed
FAIL #5 $.items[*].price lte 100
at $['items'][1]['price']: expected <= 100, got 250
Limits and edge cases
- Up to 200 assertions per run; anything more is rejected rather than truncated.
- Nothing is fetched: the payload is whatever you paste. Everything runs locally in your browser.
- JSONPath selectors are evaluated against one JSON value at a time; newline-delimited JSON must be split before running checks.
- In the line DSL the path is the first whitespace-delimited token, so a path containing spaces (
$['order id']) has to go through the JSON rules format instead. equalscompares JSON values, so unquoted DSL tokens are parsed as JSON when possible (true,42,null) and otherwise treated as strings.type integeris stricter thantype number;9.5is a number but not an integer.containsworks on arrays (membership), strings (substring), and objects (key). Usecountfor how many nodes a JSONPath selected —$.items count 2selects one array,$.items[*] count 2selects two items — andlengthfor the size of a matched array, string, or object.- A value comparison must hold for every matched node, and a path that matches nothing fails; use
not_existswhen absence is what you mean. - Regexes use Rust regular expressions. They are not JavaScript regex literals, so write
^u-\d+$rather than/^u-\d+$/. - Turning off case sensitivity affects string equality, string/array contains checks, and regex matching.
FAQ
Is this the same as JSON Schema validation?
No. JSON Schema validates a document shape with a schema language. This tool runs explicit assertions against JSONPath selections. It is useful for spot checks such as “the status is ok”, “there are two items”, or “every price is below 100”.
Can one JSONPath match multiple values?
Yes. Value comparisons must pass for every matched value. For example, $.items[*].price lte 100 fails if any item price is over 100 and reports the first failing location.
What is the difference between count and length?
count asserts how many nodes the JSONPath selected, and length asserts the size of each node it selected. For a two-item array, $.items count 1 and $.items length 2 both pass, while $.items[*] count 2 passes because the wildcard selects each item separately. When a count check fails on a single matched array, object, or string, the report says so and points at length.
When should I use JSON rules instead of the line DSL?
Use JSON rules when another tool or script generates the assertions. The line DSL is quicker to type by hand; the JSON array form is easier to serialize and review in automation.
Does the tool fetch URLs or call an API?
No. It only evaluates the JSON payload you paste. Fetch the response with curl, your browser, or another tool first, then paste the JSON here.
Developer & Automation Access
Run it from the terminal
Same engine as this page, headless — via the gizza CLI:
gizza tool json-assertion-runner '{"status":"ok","items":[{"sku":"A1","price":9.5},{"sku":"B2","price":250}],"user":{"id":"u-42","roles":["admin","dev"]}}' 'assertions=$.status equals ok
$.items length 2
$.items[*].price gt 0
$.user.roles contains admin'New to the CLI? Get gizza →
Open it by URL
Pre-fill and auto-run this tool with query parameters — the names match the API/CLI:
https://gizza.ai/tools/json-assertion-runner/?payload=%7B%22status%22%3A%22ok%22%2C%22items%22%3A%5B%7B%22sku%22%3A%22A1%22%2C%22price%22%3A9.5%7D%2C%7B%22sku%22%3A%22B2%22%2C%22price%22%3A250%7D%5D%2C%22user%22%3A%7B%22id%22%3A%22u-42%22%2C%22roles%22%3A%5B%22admin%22%2C%22dev%22%5D%7D%7D&assertions=%24.status%20equals%20ok%0A%24.items%20length%202%0A%24.items%5B%2A%5D.price%20gt%200%0A%24.user.roles%20contains%20admin&rules_format=auto&output=text&case_sensitive=true&stop_on_first_failure=trueMachine-readable descriptor: tool.json — title + parameters JSON Schema for agents.
