JSON Schema Validator
Validate a JSON document against a JSON Schema — with precise error paths, line/column locations and a schema health check.
Paste a JSON Schema on the left and the JSON document you want to check on the
right. The document is validated in your browser against every keyword the schema uses
— types, required properties, patterns, ranges, $ref references,
allOf/anyOf/oneOf/not,
if/then/else and more — and every failure is
reported with the exact JSONPath ($.users[2].email) and
JSON Pointer (/users/2/email) of the offending value, plus its
line and column in your document. The draft is detected from $schema
(draft-04 through 2020-12) and the schema itself gets a health check for typos,
unresolvable references and invalid keyword values.
Schema (JSON Schema — draft-04 to 2020-12)
waiting for a schemaDocument (the JSON to validate)
waiting for a documentOptions
In the JSON Schema spec, format is an annotation by default, but most
validators treat it as a real check — pick errors, warnings or off. Deep
uniqueItems compares {"a":1,"b":2} and {"b":2,"a":1} as
equal; stringified does not.
Result
Validation errors
| # | Path | Keyword | Problem | Location |
|---|
Click a location to jump to the exact value in the document pane. Paths use
JSONPath ($.users[2].email) and JSON Pointer
(/users/2/email, RFC 6901) — the same two notations most
validators and linters use, so you can paste them straight into your issue tracker
or log lines.
Warnings (format checks)
| # | Path | Keyword | Problem | Location |
|---|
Schema health check
Schemas are code, and code has bugs. This pass walks your schema and flags things that
will silently misbehave: $ref targets that don't resolve, unknown
keywords (typos like requred), non-numeric bounds, invalid regexes and
draft-specific keyword mismatches.
Try a sample
How to read a validation error
Every error names three things: where, which rule and why.
The path is a $-rooted JSONPath — object keys with dots, array
indices in brackets — and the JSON Pointer is the same location in the
RFC 6901 form that ajv, jsonschema and most API gateways
emit, so the two notations always agree. The keyword is the schema rule that failed
(required, type, maximum …) and the
message states the expectation in plain English. Clicking the line/column jumps the
document pane to the exact value that failed, which is the fastest way to fix real
payloads: read the path, jump, fix, re-validate.
One subtlety: for required and similar "missing thing" errors there is no
value at the path — the location then points at the object that should contain
it, and the message names the missing property. For composition keywords
(anyOf, oneOf) the summary row is followed by detail rows
showing the first failure inside each branch, because "doesn't match any branch" is
rarely actionable on its own.
Drafts at a glance
The $schema declaration selects the draft, and a few keywords changed
meaning between drafts. This validator detects the draft from $schema
and applies the right semantics (draft-07 is assumed when $schema is
absent):
| Draft | What changed that matters |
|---|---|
draft-04 | exclusiveMinimum/exclusiveMaximum are booleans that modify minimum/maximum; items is an array of positional schemas with additionalItems. |
draft-06 | Same boolean exclusives as 04; minimum/maximum may be any number, not just integers. |
draft-07 | Exclusives become numbers; adds contains, propertyNames and if/then/else. A $ref overrides sibling keywords. |
2019-09 | $ref now applies alongside sibling keywords; $defs replaces definitions. |
2020-12 | Positional array schemas move to prefixItems; items covers all items (and may be false to forbid items). |
Common schema pitfalls
- Forgetting
required.propertiesonly constrains keys that are present — an object with no properties still validates. Every optional-by-default key is a bug waiting to happen. - Leaving
additionalPropertiesopen. Without"additionalProperties": false, typos in key names (emial) pass silently. For strict APIs, close it. integervsnumber.1.0is an integer in JSON Schema (it has no fractional value), but1.5is not. If your API sends counts as floats, decide deliberately which one you want.$refand siblings. In draft-07 and earlier, keywords next to a$refare ignored — a classic source of "my constraint does nothing". UseallOfto combine, or move to 2019-09+ where siblings apply.enumwith the wrong type.["0"](string) and[0](number) are different enums. JSON has no type coercion — the values must match exactly.- Recursive schemas.
$refcycles are legal and supported here, but a runaway document will hit the recursion limit and report it as an error instead of hanging your browser.