gizmobench
BrowseDaily

JSON Schema Validator

Paste a schema into the schema pane and the JSON you want checked into the instance pane, and every failure is listed with its pointer in the document, its pointer in the schema and one sentence saying what is wrong. Validation is draft 2020-12, written into this page rather than delegated: it names the keywords it checked and, when your schema uses one it does not implement, it names that too. References resolve inside the schema you paste, so a $ref to an http or https URL is refused with the URL quoted back instead of being fetched, and a schema that refers to itself is followed to a bounded depth and then stopped.

Every failure appears here, with its path in the document and in the schema.

Draft
2020-12
Result
Waiting
Errors
waiting
Refs
Local only
  • id given as the string "42"schema wants an integer
    2 errors: the type and the missing email
  • A $ref to an https URLremote schema
    refused, nothing is fetched
  • A schema that refers to itselfrecursive $ref
    validated to a bounded depth, then stopped
A reference is resolved here or it is refused. A $ref to a pointer, to an $anchor or to an $id declared inside the schema you pasted resolves against that text. A $ref to an http or https URL is refused with the URL quoted back, because fetching it would send your schema somewhere and would let a stranger decide what your document is measured against. A schema that refers to itself is followed while the document keeps getting deeper, then stopped, and the result says so rather than claiming a clean bill of health it never earned.

Common questions

Which draft is this, and which keywords does it actually check?
Draft 2020-12. It checks type, enum, const, required and dependentRequired; the numeric bounds minimum, maximum, exclusiveMinimum, exclusiveMaximum and multipleOf; the string bounds minLength, maxLength and pattern; the array keywords prefixItems, items, contains, minContains, maxContains, minItems, maxItems and uniqueItems; the object keywords properties, patternProperties, additionalProperties, propertyNames, minProperties, maxProperties and dependentSchemas; and the applicators $ref, $defs, allOf, anyOf, oneOf, not and if/then/else, including boolean schemas. It does not implement $dynamicRef, $dynamicAnchor, unevaluatedProperties, unevaluatedItems, the contentEncoding family, or the draft-07 spellings definitions and dependencies. When your schema uses one of those, the page lists it under the result rather than passing over it in silence. It also lists any key in a schema position that is not a draft 2020-12 keyword at all: a misspelt "requird" is a valid annotation by the specification, so it constrains nothing and every document sails through, and that is worth being told.
Will it follow a $ref to another schema on the web?
No, and that is deliberate. A $ref to an http or https URL is refused before any keyword runs, with the URL quoted back and a suggestion: paste the target into $defs and point the $ref at it, for example "#/$defs/user". Nothing is requested from the network, so your schema is never sent anywhere and no stranger gets to decide what your document is measured against. A pointer such as "#/$defs/address", a "#name" reference to an $anchor, and a URL that the schema you pasted itself declares as an $id all resolve locally, because in each case the text is already in front of the checker.
What happens with a schema that refers to itself?
It is followed as long as the document keeps getting deeper, and then it stops. Three limits hold: 64 levels of the document, 250,000 keyword checks, and a guard that refuses to re-enter the same subschema at the same position in the document, which is what catches a schema whose root is simply {"$ref": "#"}. When a limit stops the run the result reads Bounded rather than Valid, and the reason is printed under the stage. Nothing below the limit was checked, and calling that valid would be the one dishonest answer available.
Why is it complaining about my schema instead of checking my document?
Because a schema with a mistake in it usually asserts nothing, and a document sailing through such a schema is worse than an error message. The schema is read first: a type that is not one of the seven JSON Schema types, a required that is not an array of names, a multipleOf of zero, a pattern that is not a valid regular expression, or a subschema that is a number rather than an object all stop the run and name both the keyword and the place in the schema where it sits, so you can go straight to it.
What do the two paths under each error mean?
The first is a JSON pointer into your document and the second is a JSON pointer into your schema. An error reading /id, must be integer, schema: /properties/id/type says the value at /id in the document broke the type keyword at /properties/id/type in the schema. The root of a document has an empty pointer, which reads as nothing at all, so it is printed as (root). Errors come deepest first: a child's failure is listed above the parent's missing-property failure.
Is there a size limit, and how many errors will it list?
Each box takes up to 1,000,000 characters; byte size depends on the characters and encoding. Longer input is refused rather than cut short. Instance depth is bounded at 64 and a run at 250,000 keyword checks. Up to 200 errors are listed, with a notice when more exist. Copy report uses the available report as plain text, paths included.
Does it check format, like email or date-time?
No. In draft 2020-12 format is an annotation by default rather than an assertion, so a string marked "format": "email" is not rejected here for failing to look like an email. That is the specification's own default, and this page states it: whenever your schema uses format, the keyword is listed under the result as present and not checked, so you are never left guessing whether a constraint was applied.
Does my JSON leave the browser?
No. Both boxes are read and checked in your own browser, there is no account and nothing is uploaded, which matters because the document you want validated is usually a real API response or a production record. Your draft is remembered in this browser alone so the page opens where you left it, and the Start over button at the top of the page forgets it.
Can it validate Draft 7 or Draft 4 schemas?
No. The checker implements its stated Draft 2020-12 subset. Changing a $schema URI is not a conversion between drafts; keywords such as Draft-07 definitions and dependencies are not checked, and the page reports them. Use a validator that explicitly supports the dialect you need.
How do I check an array of nested JSON objects?
Provide an array schema with items describing each object. For example, {"type":"array","items":{"type":"object","required":["id"],"properties":{"id":{"type":"integer"}}}} rejects [{"id":"1"}] at /0/id. Add additionalProperties:false if unexpected fields should fail. Missing and null values are different; a required field still needs a type that allows null when null is valid.
Can it check patterns, email, dates or YAML?
The pattern keyword checks JavaScript regular expressions and reports an invalid expression in the schema. Format values such as email, date and date-time are annotations and are not asserted. Input in both boxes must be JSON. Convert supported YAML values separately if needed; the page is not a YAML, OpenAPI, database or schema.org validator.
Does this generate a schema or integrate with Java, Python or AJV?
It is a manual browser checker, with no package, CLI, framework integration or remote schema fetch. Use [JSON to JSON Schema](/json-to-json-schema) to infer a starting schema from a sample, then review it before validation. A successful bounded run concerns the implemented constraints, not your entire application contract.

Validation runs in your browser against JSON Schema draft 2020-12, with the keywords implemented in this page: type, required, enum, const, the numeric, string, array and object bounds, and the $ref, $defs, allOf, anyOf, oneOf, not and if/then/else applicators. It does not assert format and does not implement $dynamicRef, unevaluatedProperties or unevaluatedItems, so every keyword it skipped is listed beside the result. References resolve inside the schema you paste and nowhere else: a $ref to an http or https URL is refused rather than fetched, the instance is followed 64 levels deep and no further, and error text is quoted back as text, never as markup.