JSON Schema Tutorial: Contracts for Your JSON
JSON tells you what the data IS; JSON Schema tells you what the data is ALLOWED to be. It's the contract layer — machine-checkable rules that catch the missing field and the string-where-a-number-belongs before they reach production.
In short
JSON Schema is a JSON-based contract language that describes what a JSON document is allowed to contain: type constrains value kinds, properties defines an object's fields, required lists mandatory fields, and additionalProperties: false closes the object to surprises. It composes recursively for nested objects and arrays, and tools can infer a draft schema automatically from a sample payload.
Your first schema
A schema is itself JSON: it describes the shape a document must have. The core keywords cover 90% of real usage — type constrains the kind of value, properties describes an object's fields, required lists which fields must exist, and additionalProperties: false closes the object to surprises.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"name": { "type": "string", "minLength": 1 },
"age": { "type": "integer", "minimum": 0 },
"email": { "type": "string", "format": "email" }
},
"required": ["name", "email"],
"additionalProperties": false
}Nesting and arrays
Schemas compose exactly like the data they describe: a property's schema can be a full object schema, and arrays take an items schema applied to every element — with minItems/maxItems and uniqueItems for the list itself. This recursive composition is the whole mental model; once it clicks, any payload's schema writes itself.
{
"type": "object",
"properties": {
"items": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"properties": {
"sku": { "type": "string", "pattern": "^[A-Z]{2}-\\d+$" },
"qty": { "type": "integer", "minimum": 1 },
"price": { "type": "number", "exclusiveMinimum": 0 }
},
"required": ["sku", "qty", "price"]
}
}
}
}The keywords you'll actually use
Beyond the basics: enum locks a value to a fixed set ("status": {"enum": ["active","paused"]}); pattern applies a regex to strings; format adds semantic checks (email, uri, date-time, uuid) — validators treat it as annotation or assertion depending on configuration; oneOf/anyOf express alternatives (a payment is card OR bank transfer); $ref reuses definitions so the Address schema is written once. Resist the deep end on day one — type, properties, required, items, and enum carry most production schemas.
| Keyword | Purpose | Example |
|---|---|---|
| type | Constrains the value's kind | "type": "string" |
| required | Lists fields that must be present | "required": ["name", "email"] |
| enum | Locks a value to a fixed set | "enum": ["active", "paused"] |
| pattern | Applies a regex to strings | "pattern": "^[A-Z]{2}-\\d+$" |
| format | Adds semantic checks | "format": "email" |
| $ref | Reuses a schema definition | "$ref": "#/definitions/Address" |
Don't write schemas from scratch — generate them
The fastest path from payload to contract is inference: paste a representative sample into our JSON to JSON Schema generator and get a draft schema with types and structure already filled in. Then harden it by hand — tighten required (generators can only guess from presence), add enums, ranges and formats the sample couldn't express. Wire the result into CI (ajv in JS, jsonschema in Python) or use it for editor autocomplete via $schema, and your API contract enforces itself from then on. Before that, check a few real payloads against the finished schema with our JSON Validator.
Sources
Frequently asked questions
Where is JSON Schema actually used?
Everywhere contracts matter: OpenAPI request/response definitions are JSON Schema, editors use it for config autocomplete and inline validation (that's what a $schema key in tsconfig-style files does), CI pipelines validate fixtures against it, and form generators build UIs straight from it.
Is the generated schema from a sample production-ready?
It's a strong draft, not a contract: a sample shows what was present, not what's mandatory or what ranges apply. Review required, add constraints, and feed multiple representative samples for tighter inference — then it's production-ready.
Which draft of JSON Schema should I use?
2020-12 for new work — it's what current OpenAPI (3.1) and modern validators target. If a tool in your chain only speaks draft-07 (still common), stay consistent across the chain; mixing drafts is where mysterious validation differences come from.
Paste a real payload into JSON to JSON Schema — get the inferred contract in seconds, then harden it by hand.
Generate a schemaKeep working
Related tools
JSON to JSON Schema
Paste a JSON or XML sample — the format is auto-detected — and get typed JSON Schema models with names, nesting and nullability inferred for you.
JSON Validator
Strict RFC 8259 validation with the exact line and column of every error — plus one-click repair for broken JSON.
JSON Formatter
Format, beautify, and validate JSON instantly in a professional VS Code-style editor — free, fast, and 100% private.
JSON to TypeScript
Paste a JSON or XML sample — the format is auto-detected — and get typed TypeScript models with names, nesting and nullability inferred for you.
JSON Schema Validator
Paste a document and a JSON Schema, press Validate, and get every violation at once — each one located by its JSON Pointer path and named by the keyword that failed. Runs Ajv entirely in your browser.