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 }
  • name is missing, but required demands it.
  • age is -1, below the minimum of 0; and role is "owner", which isn't in the enum.
  • extra isn't declared and additionalProperties: false forbids unknown keys. (The email format 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:

KeywordApplies toWhat it does
typeanyConstrains the JSON type: string, number, integer, boolean, object, array, null.
propertiesobjectDefines a sub-schema for each named property.
requiredobjectLists properties that must be present.
additionalPropertiesobjectSet to false to reject any property not listed in properties.
itemsarrayThe schema every array element must match.
enumanyRestricts the value to a fixed set of allowed options.
formatstringSemantic hint: email, uri, date-time, uuid, ipv4
minimum / maximumnumberInclusive numeric bounds.
minLength / maxLengthstringString length bounds.
patternstringA regular expression the string must match.
$ref / $defsanyReuse 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 definitions to $defs and introduces prefixItems for 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, and enums).

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?).

Related articles