JSON document

JSON Schema

Result

Paste a document and a schema — validation runs as you type.

Validating against a schema, and why the path matters

A JSON Schema describes the shape a document is supposed to have — which fields must exist, what type each one is, which values are allowed. Validation is asking one question: does this document satisfy that description? The useful part of the answer is never "no". It is which field, and why.

That is what this page gives you. Paste a document on the left, a schema in the middle, and every failure comes back with the path that produced it: /subscribers/2/msisdn rather than a message about the document as a whole. On a 400-line API response with one bad field buried in an array, that path is the difference between a fix and an afternoon.

Validation runs against Ajv, which is the same validator sitting inside Fastify, and behind a great many Express and NestJS request pipelines. So the answer you get here is the answer your server will give — including the awkward parts, like the fact that additionalProperties defaults to permitting anything and a typo'd field name therefore passes silently until you say otherwise.

Draft 2020-12 is the default and covers most schemas written in the last few years. Older documents declaring draft-07 in their $schema are handled too. Everything runs in your browser — the document is not uploaded, which matters when the thing you are validating is a real API response.

How to use it

  1. Paste the document – The JSON you actually received or are about to send. A real payload beats a trimmed-down one, because the failures you care about are usually in the parts people trim.
  2. Paste the schema – Either draft you have. If the schema declares a $schema keyword it is respected; if not, draft 2020-12 is assumed.
  3. Read the failures in order – Each one names the instance path, the schema rule that rejected it, and the message. Fix the first one and revalidate — later errors are often consequences of it.
  4. Fix the document, or fix the schema – Roughly half the time the schema is what is wrong. A required field nobody sends, or a pattern written against an example rather than the real format, will show up here as a document problem.

If everything validates and you expected it not to, check for "additionalProperties": true — which is the default when the keyword is absent. A schema without it accepts any field you did not describe, so a payload with msisdnn instead of msisdn passes validation while breaking everything downstream. Setting "additionalProperties": false on your objects is the single highest-value line you can add to a schema.

One document, four failures

A SIM provisioning response checked against the schema the service publishes. Four things are wrong and every one of them is the kind that gets through code review: a status outside the allowed set, a missing required field, a number where a string was specified, and an ICCID two digits short of the 19 the pattern demands.

provisioning responseschema check
response.json3 subscribers
{
  "subscribers": [
    { "msisdn": "447700900142",
      "iccid": "8944500102198765432",
      "status": "pending" },
    { "msisdn": "447700900198",
      // no iccid
      "status": "active" },
    { "msisdn": 447700900211,
      "iccid": "89445001021987654",
      "status": "active" }
  ]
}
failures4 problems
at /subscribers/0/status
  enum allowed: "active",
  "suspended", "terminated"

at /subscribers/1
  required missing property
  "iccid"

at /subscribers/2/msisdn
  type must be string

at /subscribers/2/iccid
  pattern must match
  ^[0-9]{19}$ — this one is 17

Where this earns its place

An API is rejecting your request and the message is unhelpful

"400 Bad Request" with no body is common, and infuriating. If the service publishes a schema — most OpenAPI specs embed one per endpoint, and you can lift it out with the OpenAPI viewer — validating your request body locally tells you what the server would not.

Writing the schema in the first place

Schema authoring is iterative: write a rule, test it against a document you know is good and one you know is bad, adjust. Doing that loop in a browser tab is considerably faster than doing it through a test suite, and it stops you shipping a pattern that only ever matched your one example.

Configuration validation

Schemas are not only for APIs. A schema over your service's configuration turns "the app crashed on startup with a null pointer" into "config.retries must be an integer". Several editors will even autocomplete a config file from its schema once you point $schema at one.

Checking an event payload against a contract

Message queues have the same problem as APIs and less tooling around it. If your team keeps schemas for its events, validating a captured message against the contract is the fastest way to find out whether the producer or the consumer is at fault.

What you get back

  • Every failure, not just the first — Ajv is run in all-errors mode, because fixing one field at a time through six round trips is nobody's idea of a good afternoon.
  • The instance path for each failure, in JSON Pointer form, so an error inside an array element names the element.
  • The schema rule that rejected the value, so you can find the line in the schema that is doing it.
  • Draft 2020-12 and draft-07, chosen from the schema's own $schema keyword.
  • Format checking for date-time, email, uri, uuid and the rest, which plain Ajv leaves off by default.
  • A clear pass state. "Valid" means valid — not "no errors found", which is a different and weaker claim.
  • Both panes stay in your browser. No upload, no logging.

Questions that come up

My schema passes everything. What am I missing?

Almost certainly additionalProperties. When the keyword is absent it defaults to true, so an object schema accepts every field you did not mention — including misspellings of the ones you did. A schema that lists five properties and omits "additionalProperties": false will happily accept a document containing none of them plus five others, as long as nothing is required. The second thing to check is required: listing a property under properties does not make it mandatory.

Which draft does it use?

Draft 2020-12 by default, and draft-07 when the schema says so in its $schema. The two differ in ways that will bite you if you mix them — most visibly, draft 2020-12 replaced items as a tuple with prefixItems, so a draft-07 tuple schema validated as 2020-12 quietly stops checking positions. If your array rules seem to have stopped working, that is usually why.

Can it follow $ref to another file?

Not to a URL — the page makes no network requests, deliberately. References inside the same document work normally, including $defs, which is where most schemas keep their shared pieces. For a multi-file schema, bundle it first; $ref resolution across files is a build-time concern rather than a validation one.

What is the difference between this and the JSON Validator?

JSON Validator answers "is this well-formed JSON?" — a syntax question, and the one you want when a parser is throwing. This page answers "does this well-formed JSON match the shape it is supposed to have?" A document can be perfect JSON and still be wrong for its purpose, which is the whole reason schemas exist.

Are my numbers safe?

Long integers are worth watching everywhere on this site, and here the honest answer is that validation is checking types and ranges rather than reproducing your document, so nothing you paste is rewritten or handed back. If you need a payload with 19-digit identifiers preserved exactly through a conversion, that is what JSON Formatter and the converters are built for — the long read on why explains what goes wrong elsewhere.

Related tools

Further reading

  • Understanding JSON Schema – The official guide, and genuinely the best place to start — it is written as a tutorial rather than as a specification.
  • Draft 2020-12 release notes – What changed from draft-07, including the prefixItems split that silently loosens old tuple schemas.