Tools
Guides

JSON Schema Validator

JSON

Validate JSON against a JSON Schema (Draft-07 / 2019-09 / 2020-12) with per-field violations, or infer a schema from a sample.

100% client-side No backend

Remote URLs are not fetched; paste your JSON directly.

Schema
Data
Enter a schema and data (validate) or a sample (infer).
On this page

What is a JSON Schema tool?#

A JSON value on its own tells you what the data is — a string here, a number there. It does not tell you what the data should be: whether age must be a non-negative integer, whether email is required, whether tags is allowed to be empty. JSON Schema is the vocabulary for saying those things. You write a schema — a small JSON document that describes a shape — and a validator checks whether a piece of data fits that shape, field by field.

This page does two jobs with one schema engine. Validate takes a schema and a data document and tells you exactly which fields violate which rules, each one pinned to its path in the document. Infer goes the other way: hand it a sample JSON value and it writes a Draft-07-style schema for you, by walking the structure and recording the type of every field. The two compose naturally — infer a schema from a representative sample, then validate every future document against it.

Validation runs on the same Ajv engine production code uses, with three drafts selectable (Draft-07, 2019-09, 2020-12) and the strict-mode guard relaxed, so a slightly non-strict schema is tolerated rather than refused outright.

How to use it#

  1. Pick a mode from the toolbar toggle:
    • Validate (the default): paste your schema on the left, your data on the right.
    • Infer: paste a sample JSON value on the left, read the generated schema on the right.
  2. In Validate mode, choose the Draft the schema is written against — Draft-07 covers the great majority of schemas in the wild; pick 2019-09 or 2020-12 only if your schema uses features those drafts introduced.
  3. Choose an Indent for the output — 2 or 4 spaces. In Infer mode this controls the generated schema’s formatting.
  4. The right pane shows either the data document (Validate) or the inferred schema (Infer). The pane labels swap to match the mode.
  5. In Validate mode, the Violations panel below the panes lists every breach as path — reason. The root of the document is shown as (root); a nested field appears as its JSON Pointer, like /age.
  6. Click Copy on the right pane to grab the inferred schema or the data, or Sample / Clear to load or reset.

Results compute as soon as both inputs parse. A schema or data syntax error is reported with its exact row and column, tagged as a schema, data, or compile problem so you know where to look.

Key features#

  • Two modes, one engine. Validate documents, or generate a schema from a sample, with the same trusted validator underneath.
  • Three drafts. Draft-07, 2019-09, and 2020-12 each load only their own compiled validator, so you are always validating against the draft you actually target.
  • All errors, not just the first. Every violation is collected, so a document with five problems shows five problems instead of forcing five round trips.
  • Path-pinned violations. Each breach points at its location in the document — (root) for whole-document problems, or a precise pointer like /user/address/zip.
  • Strict mode relaxed. A schema with an unknown keyword or a missing top-level type is tolerated and run, not rejected at compile time — the right behaviour for a tool whose job is to check, not to lecture.
  • Local only. Schemas and data are processed in your browser. Nothing is uploaded.

Worked example#

A user object must have a name, and age must be a non-negative integer. Paste this schema on the left in Validate mode:

{
  "type": "object",
  "properties": {
    "name": { "type": "string" },
    "age": { "type": "integer", "minimum": 0 }
  },
  "required": ["name"]
}

Now test a document that breaks both rules — missing name, and a negative age:

{
  "age": -3
}

The Violations panel reports two breaches, each pinned to where it happened:

(root) — must have required property 'name'
/age   — must be >= 0

The (root) path tells you the missing required property is a document-level problem; /age points straight at the offending field. Fix the data to {"name":"ada","age":36} and the status flips to valid with an empty violations list. The reason text is Ajv’s own keyword wording, kept verbatim so it matches what your production logs will say.

FAQ#

Draft-07, 2019-09, or 2020-12 — which should I pick?#

Draft-07 is the pragmatic default: the overwhelming majority of schemas in tutorials, libraries, and OpenAPI specs target it, and everything you are likely to need (type, properties, required, minimum, format, $ref) works there. Move to 2019-09 or 2020-12 only when your schema explicitly uses features those drafts added — such as unevaluatedProperties or the revised $ref behaviour. Picking the wrong draft usually still works, but the safe choice is the draft the schema author intended.

Why are the violation messages in English?#

They are Ajv’s own reason text for each keyword (must have required property, must be >= 0, and so on), passed through unchanged. The point is consistency: these are the exact strings your server-side validation will log, so matching them here makes a mismatch trivially grep-able in production.

What does “strict mode relaxed” mean?#

Ajv’s strict mode rejects schemas it considers sloppy — an unknown keyword, a $ref it cannot resolve, a missing type. That is useful in a build pipeline but wrong for a validator tool, whose job is to check data against whatever schema you hand it. This page turns strict mode off, so a non-strict schema compiles and runs instead of throwing.

Can I infer a schema and then validate against it?#

Yes — that is the intended round trip. Paste a representative sample in Infer mode, copy the generated schema, switch to Validate, and paste the schema back on the left. The inferred schema re-validates the original sample cleanly, and from then on you can check every new document against it.