JSON Schema examples
Schemas that do something, from a five-line object check up to conditionals and reusable definitions.
Last reviewed
A minimal object schema
Two things to note. `required` is a list of names, not a flag on each property — a property being defined does not make it required. And `additionalProperties: false` is what turns the schema from a minimum bar into a contract; without it, any extra field passes.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["id", "email"],
"properties": {
"id": { "type": "integer", "minimum": 1 },
"email": { "type": "string", "format": "email" },
"name": { "type": "string", "maxLength": 120 }
},
"additionalProperties": false
}Nullable fields
JSON Schema has no `nullable` keyword. A field that may be null is a union of types.
{
"properties": {
"retiredOn": { "type": ["string", "null"], "format": "date" }
}
}Enums and constants
{
"properties": {
"status": { "enum": ["draft", "active", "archived"] },
"version": { "const": 2 }
}
}Arrays
`items` constrains every element. `prefixItems` with `items: false` describes a fixed-length tuple — in drafts before 2020-12 this was written as an array-valued `items`, which is the most common incompatibility between draft versions.
{
"properties": {
"tags": {
"type": "array",
"items": { "type": "string", "minLength": 1 },
"minItems": 1,
"uniqueItems": true
},
"point": {
"type": "array",
"prefixItems": [{ "type": "number" }, { "type": "number" }],
"items": false
}
}
}Reusable definitions
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$defs": {
"address": {
"type": "object",
"required": ["city", "country"],
"properties": {
"city": { "type": "string" },
"country": { "type": "string", "pattern": "^[A-Z]{2}$" }
}
}
},
"type": "object",
"properties": {
"billing": { "$ref": "#/$defs/address" },
"shipping": { "$ref": "#/$defs/address" }
}
}Conditional requirements
if/then/else expresses "when this field has this value, these other fields are required" — the rule that otherwise ends up duplicated in application code.
{
"type": "object",
"properties": {
"method": { "enum": ["card", "invoice"] },
"cardLast4": { "type": "string", "pattern": "^[0-9]{4}$" },
"poNumber": { "type": "string" }
},
"if": { "properties": { "method": { "const": "card" } } },
"then": { "required": ["cardLast4"] },
"else": { "required": ["poNumber"] }
}What a validation failure looks like
Errors are reported as a JSON Pointer into the document plus the keyword that failed. That pointer is what lets an editor jump to the offending line rather than making you search for it.
/email must match format "email"
/tags/1 must NOT have fewer than 1 characters
/ must have required property 'id'
/status must be equal to one of the allowed valuesGenerating a first draft
Inferring a schema from a real payload gets the structure right in seconds. It cannot infer intent: everything present becomes required, formats are guessed from shape, and an enum looks like a plain string. Generate, then tighten — the generated draft is a starting point, not a contract.
Keep reading
- JSONPath examples — One sample document, and the expressions people actually need against it, each with the result it produces.
- JSON API response examples — The response shapes you meet in practice, and what each convention costs the client that consumes it.