Comprehensive reference for json schema reference covering essential concepts, practical examples, and production best practices.
Json Schema is a declarative format for describing the structure, constraints, and semantics of JSON data. Use it when validating input, documenting APIs, or enforcing consistency across services. It is the backbone of reliable JSON interchange in distributed systems.
A JSON Schema defines a JSON object with a root set of keys. The most essential keys are type, properties, and required.
{
"type": "object",
"properties": {
"id": { "type": "integer" },
"name": { "type": "string", "minLength": 1 },
"active": { "type": "boolean" }
},
"required": ["id", "name"]
}
type can be "object", "array", "string", "number", "integer", "boolean", or "null".properties maps field names to their schemas. Each property can have its own type, format, default, example, or nested schemas.required lists keys that must be present and non-null.To validate a JSON document against a schema:
jsonschema -s schema.json -d data.json
This command returns exit code 0 on success, 1 on failure. On failure, it prints a detailed error:
{
"error": "Invalid JSON",
"schema": { "file": "schema.json" },
"instance": { "file": "data.json" },
"messages": [
"instance.id: type mismatch; expected integer but found string",
"instance.name: missing required property",
"instance.active: missing required property"
]
}
The jsonschema tool (from jsonschema Python package) is the most reliable CLI validator. It supports:
--strict for strict mode: unknown keys fail validation.--verbose to list all validation errors.--draft-07 to explicitly use JSON Schema Draft 07.Arrays are validated with items, minItems, maxItems, and uniqueItems.
{
"type": "array",
"items": {
"type": "object",
"properties": {
"label": { "type": "string" },
"value": { "type": "number" }
},
"required": ["label", "value"]
},
"minItems": 1,
"uniqueItems": true
}
items can be a single schema (applies to all array elements) or an array of schemas (each element uses a schema at that index).uniqueItems: true requires all array elements to be distinct (deep equality).minItems: 1 ensures at least one element.Use $ref to reuse schemas across documents.
{
"$id": "https://example.com/schemas/user.json",
"type": "object",
"properties": {
"profile": { "$ref": "https://example.com/schemas/person.json" },
"settings": { "$ref": "#/definitions/Preferences" }
},
"definitions": {
"Preferences": {
"type": "object",
"properties": {
"theme": { "type": "string", "enum": ["light", "dark"] },
"notifications": { "type": "boolean" }
}
}
}
}
$ref resolves relative to the current schema’s base URL ($id).#/definitions/Preferences references a local definition.$ref supports both absolute URLs and relative paths.oneOf, anyOf, allOfUse oneOf for mutually exclusive structures:
{
"oneOf": [
{
"type": "object",
"properties": { "type": { "const": "user" } },
"required": ["type"]
},
{
"type": "object",
"properties": { "type": { "const": "admin" } },
"required": ["type"]
}
]
}
anyOf: at least one condition must be true.allOf: all conditions must be true.allOf is critical for composing schemas:
{
"allOf": [
{ "$ref": "base-entity.json" },
{ "$ref": "user-roles.json" },
{ "properties": { "metadata": { "type": "object" } } }
]
}
Use format to validate string, date, or URI formats:
{
"type": "string",
"format": "email"
}
Common formats: date-time, time, date, uri, email, hostname, ipv4, ipv6, uuid.
format: "date-time" expects ISO 8601: 2023-04-05T12:34:56Z.format: "email" validates against RFC 5322.Register custom formats via format with a function or external validation:
{
"type": "string",
"format": "slug",
"pattern": "^[a-z0-9-]+$"
}
pattern is applied after format.format is not a strict test: format: "slug" with pattern: "^[a-z0-9-]+$" ensures lowercase, hyphenated identifiers.Defaults are applied during validation but not required to be present:
{
"type": "object",
"properties": {
"name": { "type": "string" },
"active": {
"type": "boolean",
"default": true
},
"createdAt": {
"type": "string",
"format": "date-time",
"default": "2023-01-01T00:00:00Z"
}
},
"required": ["name"]
}
default is applied only if the key is missing.default is not validated: a createdAt field with "2023-01-01" is valid even if the format is not ISO 8601.By default, validation collects all errors. Use allErrors: true to enable full reporting:
{
"type": "object",
"properties": {
"name": { "type": "string", "minLength": 3 },
"age": { "type": "integer", "minimum": 0 }
},
"required": ["name"],
"allErrors": true
}
allErrors, validation stops after the first error.allErrors, all errors are reported in a flat list.When additionalProperties is true, unknown keys are allowed. When additionalProperties is false, unknown keys fail validation.
{
"type": "object",
"properties": { "name": { "type": "string" } },
"additionalProperties": false
}
additionalProperties: true allows any key not listed in properties.additionalProperties: { "type": "string" } validates unknown keys against a schema.additionalProperties: false requires all keys to be declared.nullable and typenullable is a top-level feature, but it does not imply type:
{
"type": "string",
"nullable": true
}
string and null.type: ["string", "null"] is equivalent, but nullable is shorthand.Use type: ["string", "null"] when you need to validate the string with format, pattern, or enum:
{
"type": ["string", "null"],
"format": "email",
"pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
}
$idUse $id to version and reference schemas:
{
"$id": "https://example.com/schemas/v1/user.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "User",
"description": "A user account with profile and preferences."
}
$schema links to the draft specification used.$id is the canonical URI of the schema."$anchor": "User" to name a schema fragment for reuse.When using $ref, resolution follows these rules:
$ref: https://example.com/schemas/person.json.$ref: ./user.json or ../common.json."$id" sets the base URL for relative references.When a schema is included via $ref, its properties and required are merged with the current schema.
Use errorMessages to provide human-readable error feedback:
{
"type": "object",
"properties": {
"email": {
"type": "string",
"format": "email",
"errorMessages": {
"format": "Invalid email format. Must be a valid email address.",
"required": "Email is required."
}
}
},
"required": ["email"],
"errorMessages": {
"required": "All required fields must be present."
}
}
errorMessages can be a map from validation keywords to messages.errorMessages are applied per keyword: format, type, required, minLength, etc.required on null fieldsrequired: ["name"] fails if name is null, even if name exists.
{ "name": null }
required checks for the key and non-null value.null in required fields, use required with nullable:{
"type": "object",
"properties": {
"name": {
"type": ["string", "null"],
"nullable": true
}
},
"required": ["name"]
}
items vs items arrayitems: { "type": "string" } applies the same schema to all array elements.items: [ { "type": "string" }, { "type": "number" } ] expects the first element to be a string, the second a number, and so on.uniqueItems and minItems with allOfWhen combining allOf, uniqueItems applies to the merged schema:
{
"allOf": [
{ "items": { "type": "string" } },
{ "minItems": 2 },
{ "uniqueItems": true }
]
}
uniqueItems operates on the full array after merging.format on arraysformat: "date-time" on an array applies format to each element:
{
"type": "array",
"items": { "type": "string", "format": "date-time" }
}
const vs enumconst: "active" validates that the value is exactly "active".enum: ["active", "inactive"] allows either value.Use const for exact values; use enum when you need flexibility.
oneOf with discriminatorUse discriminator to select schema branches:
{
"oneOf": [
{ "$ref": "#/definitions/User" },
{ "$ref": "#/definitions/Admin" }
],
"discriminator": {
"propertyName": "role",
"mapping": {
"user": "#/definitions/User",
"admin": "#/definitions/Admin"
}
}
}
propertyName is the field name that determines the branch.mapping defines which value selects which schema.mapping is optional: if not present, use the value directly as a $ref.| Flag/Key | Effect |
|---|---|
type: "object" | Validates a JSON object |
properties | Defines key-value structure |
required | Ensures keys exist and are non-null |
additionalProperties: false | Fails on unknown keys |
allErrors: true | Collects all validation errors |
format: "email" | Validates email format |
nullable: true | Allows null value |
enum: [...] | Allows one of a set of values |
const: value | Validates exact value |
oneOf, anyOf, allOf | Conditional validation |
$ref | Reuse and reference schemas |
definitions | Local schema components |
errorMessages | Custom error text per validation step |
Use jsonschema CLI with --draft-07 --strict --verbose in production pipelines. Always validate schema against itself using jsonschema -s schema.json -d schema.json.
This page was rewritten on 10 October 2026. It replaced a templated version that was not specific to its own title. How these pages are written and checked. If anything here is wrong, tell us at [email protected] and we will correct it.
We use cookies for analytics (Google Analytics) and advertising (Google AdSense) to improve your experience and support free content. Privacy Policy