My Tool Studio
Developer Tools·4 min read

JSON Schema Validation: A Practical Guide

Valid JSON is only half the story. A payload can parse perfectly and still have a missing field, a price stored as text or an email without a domain. JSON Schema describes what correct data looks like, so those problems are caught at the door instead of three services later. This guide covers what a schema checks, how to read the errors a validator gives you, which draft to use, and how to get a first schema without writing it from scratch.

{"@type": "Article","name": "…","url": "…"}RICH RESULTArticle

Syntax checks versus structure checks

Two different questions.

A JSON validator answers one question: does this text parse? A trailing comma or a single quote fails that test. JSON Schema answers the next question: does the data have the right shape? It checks that id is an integer of at least 1, that email looks like an email, that plan is one of three values and that no unexpected fields slipped in.

APIs use schemas to reject bad requests with a clear message. Config tools use them to catch typos before deployment. Editors use them for autocomplete. The JSON Schema Validator lets you test a schema and a document side by side, in your browser, with the results updating as you type.

A worked example, error by error

Six rules, six failures.

Press Try sample. The schema describes an account: a required integer id with a minimum of 1, a required email in email format, a required plan from free, pro or team, optional seats, a tags array of unique strings, a billing address defined under $defs, and additionalProperties set to false. It also says that when plan is team, seats is required.

The sample data breaks six rules. The result lists /id must be at least 1, /email must be a valid email, /tags must not contain duplicates, /billing/country must match the pattern ^[A-Z]{2}$, property nickname is not allowed, and a missing seats property caused by the if/then rule. Fix them one by one in the data pane and watch the list shrink until the result turns green.

How to read a validation error

Three parts, three questions.

Each error row answers where, what and why. Where in the data is a JSON Pointer: /billing/country means the country key inside the billing object, and /items/3/price means the price of the fourth item, since arrays count from zero. Problem is the plain-English message. Schema rule is a pointer into the schema, such as #/properties/billing/$ref/properties/country/pattern, which tells you which keyword failed and the $ref it was reached through.

Combinator errors need a second look. anyOf fails only when no branch matches, and the message names the closest branch. oneOf fails when zero branches match, and also when two or more do, which surprises people whose branches overlap. Adding additionalProperties false to each branch, or a const discriminator such as a type field, usually makes them exclusive.

Picking a draft

Mostly a matter of what your tools support.

JSON Schema has several published drafts. Draft 7 is still the most widely supported, 2020-12 is the current one, and draft 4 lives on in older OpenAPI specs. The validator reads the $schema URL to decide, uses draft 7 when there is none, and lets you force a draft from the menu.

  • Draft 4 writes exclusiveMinimum as true or false next to minimum; later drafts give it its own number.
  • Draft 6 added const, contains and propertyNames; draft 7 added if, then and else.
  • 2019-09 split dependencies into dependentRequired and dependentSchemas and let $ref sit alongside other keywords.
  • 2020-12 replaced array-form items with prefixItems for tuples.
  • unevaluatedProperties, unevaluatedItems and $dynamicRef are not checked here; the result adds a note when a schema uses them.

Generating a first schema from data

Start from a real example, then tighten.

Writing a schema by hand for a large payload is slow. Paste a representative example into the data pane and press Generate schema from data. The generator records every type it sees, merges the objects in arrays so fields that appear in some items are listed once, marks fields present in every item as required, and adds formats for dates, emails, UUIDs, IP addresses and URLs.

Treat the result as a draft. It knows what your example contains, not what is allowed. Add minimum and maximum to numbers, enum to fields with a fixed set of values, patterns to codes, and additionalProperties false once you are sure the list of fields is complete. Then paste a few bad examples to make sure each rule catches what it should.

Formats, references and other details

Format checks are optional in the specification, so the validator has a switch for them. With Check formats on, email, date-time, date, time, duration, uuid, ipv4, ipv6, hostname, uri, uri-reference, regex and json-pointer are tested, and unknown formats are listed in a note instead of failing silently.

References to #/$defs, #/definitions, $anchor names and $id values inside the same schema are followed. Remote URLs are not fetched, so paste shared schemas into $defs and point to them locally. Everything runs in your browser, which means private schemas and production payloads stay on your machine. To check that the payload parses at all, the JSON Validator gives line-level syntax errors, and JSON to TypeScript can turn the same example into types for your code.

Try it now

Open JSON Schema Validator

The tool is one click away. No sign up, no upload, no payment.

Open JSON Schema Validator