JSON Schema Validator

Paste a schema and a document and see every rule that failed, each pointing at the value that broke it. Runs on a Rust validator in your browser — nothing is uploaded, and no external reference is ever fetched.

Files never leave your deviceNo schema yet? Generate one from a sample.
0
0

The draft is taken from the schema itself. Without a $schema keyword, 2020-12 is assumed.

A JSON Schema describes the shape a document is supposed to have — which keys exist, what types their values take, which are required, what ranges and patterns are allowed. This page checks a document against one and reports every place the two disagree, without either leaving your browser.

Reading a failure

Each failure carries two locations, and they answer different questions:

Points intoExampleAnswers
Value pathyour documentitems[0].pricewhat is wrong
Rule pathyour schema/properties/items/items/properties/price/typewhich rule says so

The value path is written the way you would reach the value in code, so items[0].price can be read straight down the document. Keys that are not plain identifiers are quoted — a key containing a dot appears as ["a.b"] rather than silently reading as two levels.

The rule path is a JSON pointer into your schema, which is how you find the keyword to change when it is the schema, not the document, that is wrong.

The draft is taken from your schema

The validator reads the $schema keyword and applies that draft's rules. Draft 4, 6, 7, 2019-09 and 2020-12 are all supported, which matters because the drafts genuinely differ:

  • exclusiveMinimum was a boolean modifier in draft 4 and became a number of its own from draft 6.
  • items as an array of schemas became prefixItems in 2020-12.
  • definitions became $defs.

A schema with no $schema keyword is validated as 2020-12.

Tip: If a schema behaves differently here than in another tool, check its $schema line first. Two validators disagreeing on the same document usually means they picked different drafts, not that one of them is wrong.

External references are refused on purpose

A $ref pointing at another file or a URL will not resolve. That is not an unfinished feature: the only way to resolve one is to fetch it, and fetching would break the promise this page makes. A validator that downloads URLs out of your schema is one that can be made to reveal which schemas you work with, and to whom.

References inside the schema work normally. Move what you need under $defs and point at it with a local pointer:

{
  "$defs": { "money": { "type": "number", "minimum": 0 } },
  "type": "object",
  "properties": { "price": { "$ref": "#/$defs/money" } }
}

Numbers keep their exact value

Validation runs on each number's source text rather than on a converted double. A 30-digit integer therefore still validates as an integer, and still compares correctly against minimum, maximum and multipleOf. This is a real difference: in a validator that parses to a double first, a large identifier is quietly damaged before any rule is applied, and the report describes a value you never sent.

Common failures and what they mean

  • want string, but got number — a type mismatch, usually a numeric field that arrived quoted or a quoted field that arrived numeric. Check what produced the document, not the schema.
  • missing properties — a required key is absent. If it is legitimately optional, the schema is what needs fixing.
  • must not have additional properties — the schema sets additionalProperties: false and the document carries a key it does not declare. Common after an API adds a field.
  • does not match pattern — a pattern or format rejected the value. Regular expressions in schemas are unanchored unless you anchor them, so a partial match counts as a match.

Limits

Ten megabytes each for the schema and the document — a ceiling on what a browser tab can hold comfortably, not on what the validator can do.

Frequently asked questions

Is my schema or my data uploaded anywhere?
No. Both are validated inside your browser tab by a Rust validator compiled to WebAssembly, and no request carries either off the device. Open your browser's network panel while validating and you will see nothing at all. That is the point when the document is a customer export, an internal API response, or a config you are not allowed to paste into someone else's server.
Which drafts does it support?
Draft 4, 6, 7, 2019-09 and 2020-12. The draft is read from the schema keyword at the top of your schema, so a schema that declares its own draft is validated by that draft's rules. If the declaration is missing, 2020-12 is assumed, which is the current specification and the safe default for a new schema.
Why does a reference to another file or URL fail?
Because resolving one would mean fetching it, and this page never makes a request. That is a deliberate trade-off rather than a missing feature: a validator that quietly downloads a URL from your schema is a validator that can be made to leak which schemas you use, and to whom. Inline what you need under the definitions keyword and the reference resolves locally.
Does it stop at the first error?
No, it reports every rule that failed, each with a pointer to the value that broke it and a pointer to the keyword that rejected it. Fixing errors one round-trip at a time is the slowest way to work through a mismatched document, so the full list is the default and the only mode.
What do the two paths in each error mean?
The first points into your document, so 'items[0].price' is the value that failed. The second points into your schema, so '/properties/items/items/properties/price/type' is the exact keyword that rejected it. Together they answer both halves of the question: what is wrong, and which rule says so.
Does it handle numbers too large for JavaScript?
Yes. Numbers keep their exact source text through the whole validation rather than being parsed into a double first, so a 30-digit integer still validates as an integer and still compares correctly against minimum and maximum. A validator written in JavaScript typically cannot do that, because the value is damaged before the rules ever run.
Is there a size limit?
Ten megabytes each for the schema and the document. That ceiling exists to keep the browser tab responsive rather than to restrict use; schemas are almost never near it, and documents that are usually belong in a streaming pipeline rather than a text box.