JSON Schema Tutorial: How to Write & Validate JSON Schema
What JSON Schema is, how to write one from scratch, the keywords you'll actually use, and how to validate JSON against it — in JavaScript, in Python, and with no code at all.
The first time bad data breaks production, it's rarely a syntax error — the JSON parses fine. It's the wrong shape: a missing email, a string where a number belongs, a status that isn't one of the values your code handles. JSON Schema is how you catch that at the boundary, before it spreads through the system. This guide takes you from zero to a working schema you can validate against.
What is JSON Schema?
JSON Schema is a vocabulary for describing the structure of JSON data — which fields must exist, what type each value should be, and what counts as valid. A schema is itself written in JSON, so the same tools that read your data can read its contract.
It answers a different question than a plain JSON validator. A JSON validator checks “is this valid JSON?” (syntax). JSON Schema checks “is this the right JSON?” (shape and constraints). You usually want both. JSON Schema shows up wherever data crosses a boundary: validating API request and response bodies, configuration files, form input, queue messages, and contract tests between services.
Your first JSON Schema, by example
Say every user object must have a name and an email, may have a non-negative age, and must have a role from a fixed list. Here is the schema that says exactly that:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": { "type": "string", "minLength": 1 },
"email": { "type": "string", "format": "email" },
"age": { "type": "integer", "minimum": 0 },
"role": { "type": "string", "enum": ["admin", "user", "guest"] }
},
"required": ["name", "email", "role"],
"additionalProperties": false
}
This document passes — every required field is present and correctly typed:
{ "name": "Ada", "email": "ada@example.com", "age": 36, "role": "admin" }
This one fails, for three separate reasons:
{ "email": "not-an-email", "age": -1, "role": "owner", "extra": true }
nameis missing, butrequireddemands it.ageis-1, below theminimumof 0; androleis"owner", which isn't in theenum.extraisn't declared andadditionalProperties: falseforbids unknown keys. (Theemailformat is a softer check — see the draft note below.)
The keywords you'll actually use
JSON Schema has a large vocabulary, but a handful of keywords cover the vast majority of real schemas:
| Keyword | Applies to | What it does |
|---|---|---|
type | any | Constrains the JSON type: string, number, integer, boolean, object, array, null. |
properties | object | Defines a sub-schema for each named property. |
required | object | Lists properties that must be present. |
additionalProperties | object | Set to false to reject any property not listed in properties. |
items | array | The schema every array element must match. |
enum | any | Restricts the value to a fixed set of allowed options. |
format | string | Semantic hint: email, uri, date-time, uuid, ipv4… |
minimum / maximum | number | Inclusive numeric bounds. |
minLength / maxLength | string | String length bounds. |
pattern | string | A regular expression the string must match. |
$ref / $defs | any | Reuse a named sub-schema — for shared types or recursion. |
How to validate JSON against a schema (in code)
A schema is only useful when something checks data against it. In JavaScript, the de-facto standard validator is Ajv:
import Ajv from "ajv";
import addFormats from "ajv-formats";
const ajv = new Ajv({ allErrors: true });
addFormats(ajv); // enables "format": "email", "date-time", ...
const validate = ajv.compile(schema);
const data = { name: "Ada", email: "ada@example.com", role: "admin" };
if (!validate(data)) {
console.log(validate.errors); // [{ instancePath, keyword, message }, ...]
}
In Python, the jsonschema library does the same:
from jsonschema import validate, ValidationError
try:
validate(instance=data, schema=schema)
except ValidationError as e:
print(e.message) # e.g. "'email' is a required property"
The important part of both is that errors come back by path — you learn exactly which field failed and why, instead of a single “invalid” boolean. Turn that into a guard at your API edge and malformed payloads never reach your business logic.
Which JSON Schema draft should you use?
The $schema line declares which version of the specification you're writing against, and it changes how some keywords behave. The practical guidance:
- Draft-07 — the most widely supported across libraries and tooling. A safe default if you're unsure.
- 2019-09 / 2020-12 — newer. 2020-12 renames
definitionsto$defsand introducesprefixItemsfor tuple validation, among other changes.
One gotcha: format (like email) is annotation-only by default in several drafts — validators such as Ajv only enforce it when you opt in (the ajv-formats line above). If you rely on format, confirm your validator actually checks it.
Write and validate schemas without code
When I'm sketching a schema or sanity-checking a payload during a review, I don't reach for a script — I use a browser tool. Ours run fully client-side, so your data never leaves the page (disclosure: I built these):
- JSON Schema Validator — paste a schema and a document, see pass/fail and every error by path.
- JSON Schema Builder — build a schema visually instead of hand-writing keywords.
- JSON to Schema — infer a starter schema from a sample, then tighten it (add
required, formats, andenums).
A common workflow: generate a draft schema from real data with JSON to Schema, refine it in the Builder, then wire the result into Ajv or jsonschema for automated checks in CI.
FAQs
What is JSON Schema used for?
Describing and validating the structure of JSON — which fields must exist, their types, and allowed values. It's used for API bodies, config files, form input, and message payloads to catch the wrong shape of data before it causes bugs.
How do I validate JSON against a schema?
Use a validator: Ajv in JavaScript, jsonschema in Python, or an online JSON Schema validator. Each reports errors by path, e.g. email is a required property.
What's the difference between JSON Schema drafts?
Drafts are spec versions. Draft-07 is the most widely supported; 2020-12 is the newest ($defs, prefixItems). Declare yours with $schema.
How do I generate a JSON Schema from existing JSON?
Infer one from a sample with JSON to Schema, then refine: add required, formats, enums, and additionalProperties: false where the shape is fixed.
Is JSON Schema the same as a JSON validator?
No. A JSON validator checks syntax (is it valid JSON?); JSON Schema checks shape and constraints (is it the right JSON?).