A JSON parser checks syntax. JSON Schema checks the document's shape: required fields, value types and allowed values.

The 2020-12 specification defines the vocabulary used in this guide.

Use the examples below to reject invalid input before business logic runs.

A schema is itself JSON

Here is a schema for a user record:

{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "User",
"type": "object",
"properties": {
"id":     { "type": "string", "format": "uuid" },
"name":   { "type": "string", "minLength": 1 },
"email":  { "type": "string", "format": "email" },
"age":    { "type": "integer", "minimum": 0, "maximum": 150 },
"role":   { "type": "string", "enum": ["admin", "editor", "viewer"] },
"tags":   { "type": "array", "items": { "type": "string" }, "uniqueItems": true }
},
"required": ["id", "name", "email"],
"additionalProperties": false
}

And a document that passes:

{
"id": "01a0fa6b-892e-796d-a7a9-e89f53df668c",
"name": "Ada",
"email": "ada@example.com",
"role": "admin",
"tags": ["founder"]
}

Remove email and validation fails with "must have required property 'email'".

Set role to "owner" and it fails the enum. Add a nickname field and it fails because additional properties are forbidden.

The keywords you will use most

type: one of object, array, string, number, integer, boolean, null. Can be a list to allow several.

properties: a schema for each named key of an object.

required: the keys that must be present. Everything else is optional by default.

additionalProperties: set to false to reject unknown keys, which catches typos.

items: the schema every array element must match.

enum: an exact list of allowed values.

minimum, maximum, minLength, maxLength, minItems: range limits.

pattern: a regular expression a string must match. The UUID regex from our UUID validation guide works here.

format: named formats such as email, uri, date-time, uuid. Validators may treat these as hints only unless you enable format checking.

Reusing pieces with $ref

{
"$defs": {
"address": {
"type": "object",
"properties": { "city": { "type": "string" }, "zip": { "type": "string" } },
"required": ["city"]
}
},
"type": "object",
"properties": {
"home": { "$ref": "#/$defs/address" },
"work": { "$ref": "#/$defs/address" }
}
}

Define a sub schema once under $defs and point at it. Refs can also target other files or URLs.

Combining schemas

oneOf, anyOf and allOf take lists of schemas.

A common use is a discriminated union: a payment is either a card with a number or a bank transfer with an IBAN, never both. if, then and else handle conditional rules such as "if country is US then zip is required".

Running validation

JavaScript with the Ajv validator. The default Ajv class only knows draft 7, so a 2020-12 schema needs the Ajv2020 class or compile throws:

import Ajv2020 from "ajv/dist/2020.js";
import addFormats from "ajv-formats";

const ajv = addFormats(new Ajv2020());
const validate = ajv.compile(schema);
if (!validate(data)) console.log(validate.errors);

Python:

from jsonschema import validate, ValidationError
try:
validate(instance=data, schema=schema)
except ValidationError as e:
print(e.message)

Command line, once you have a schema and a file:

npx ajv-cli validate --spec=draft2020 -c ajv-formats -s schema.json -d data.json

Where it pays off

API input. Reject malformed requests with a precise error before any code runs.

Config files. Point your editor at a schema and get autocomplete and red squiggles. VS Code does this through the $schema key or its settings.

Contracts between teams. A schema is a precise, testable description of what a service accepts and returns. OpenAPI documents embed JSON Schema for exactly this.

Test fixtures. Validate every fixture in CI so that a change to the data shape fails loudly.

Drafts and versions

JSON Schema has gone through several drafts.

Draft 2020-12 is current and what new work should use. Draft 7 is still very common in older tools and validators.

The keywords above work the same in both, with one exception: draft 7 spells $defs as definitions.

Always set $schema at the top of your file so tools know which rules to apply.

Before writing a schema, make sure your sample documents are valid JSON in the first place.

Our JSON formatter will catch syntax errors so you are only debugging shape problems.

A schema describes the shape of a document, so it helps to see that shape first: paste a sample into the JSON visualizer and each box in the diagram is one object or array your schema has to describe.