JSON Schema Validation: A Complete Tutorial
A complete guide to JSON Schema — writing schemas, validating data, using $ref and composition keywords, and integrating validation into your API pipeline.
Alex Chen
Senior Software Engineer
What Is JSON Schema?
JSON Schema is a vocabulary for annotating and validating JSON documents. It describes the structure of a JSON document — the types of fields, required vs optional fields, constraints on values, and relationships between fields. JSON Schema is the standard way to document API contracts, validate incoming data, and auto-generate forms, documentation, and TypeScript types.
A Simple JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://api.example.com/schemas/user.json",
"title": "User",
"description": "A registered user in the system",
"type": "object",
"required": ["id", "email", "name"],
"properties": {
"id": {
"type": "integer",
"description": "Unique user identifier"
},
"email": {
"type": "string",
"format": "email"
},
"name": {
"type": "string",
"minLength": 1,
"maxLength": 100
},
"role": {
"type": "string",
"enum": ["admin", "user", "viewer"],
"default": "user"
},
"age": {
"type": "integer",
"minimum": 0,
"maximum": 150
}
},
"additionalProperties": false
}
Type Keywords
"type": "string"— string values"type": "number"— any number (integer or float)"type": "integer"— whole numbers only"type": "boolean"— true or false"type": "null"— the JSON null value"type": "array"— JSON arrays"type": "object"— JSON objects"type": ["string", "null"]— union of types (nullable string)
Composition Keywords
{
"allOf": [
{ "$ref": "#/$defs/BaseUser" },
{ "required": ["admin_level"] }
],
"anyOf": [
{ "type": "string" },
{ "type": "integer" }
],
"oneOf": [
{ "required": ["card_number"] },
{ "required": ["bank_account"] }
],
"not": {
"properties": { "status": { "enum": ["deleted"] } }
}
}
Using $ref for Reusable Components
{
"$defs": {
"Address": {
"type": "object",
"required": ["street", "city"],
"properties": {
"street": { "type": "string" },
"city": { "type": "string" },
"zip": { "type": "string", "pattern": "^[0-9]{5}$" }
}
}
},
"properties": {
"billing": { "$ref": "#/$defs/Address" },
"shipping": { "$ref": "#/$defs/Address" }
}
}
Validating Data with ajv (Node.js)
import Ajv from 'ajv'
import addFormats from 'ajv-formats'
const ajv = new Ajv({ allErrors: true })
addFormats(ajv)
const schema = {
type: 'object',
required: ['email', 'name'],
properties: {
email: { type: 'string', format: 'email' },
name: { type: 'string', minLength: 1 },
age: { type: 'integer', minimum: 0 }
},
additionalProperties: false
}
const validate = ajv.compile(schema)
const data = { email: 'not-an-email', name: '' }
if (!validate(data)) {
console.log(validate.errors)
// [
// { keyword: 'format', dataPath: '.email', message: 'must match format "email"' },
// { keyword: 'minLength', dataPath: '.name', message: 'must NOT be shorter than 1 characters' }
// ]
}
Schema Comparison with DiffChecker Pro
When evolving a JSON Schema, comparing the old and new schema versions ensures you understand the impact of every change:
- Removing a required field = backward-compatible (for producers), breaking (for consumers that depend on it)
- Adding a required field = breaking change for existing producers
- Narrowing constraints (reducing
maxLength) = potentially breaking for existing data - Adding optional properties = always safe
Paste your old and new schema JSON into DiffChecker Pro's JSON diff mode. The structural diff highlights exactly which constraints changed, which properties were added or removed, and which required fields changed — giving you a clear impact analysis for every schema version bump.
Generating TypeScript Types from JSON Schema
npx json-schema-to-typescript user.schema.json > user.types.ts
# Result:
export interface User {
id: number
email: string
name: string
role?: 'admin' | 'user' | 'viewer'
age?: number
}
Share this article
Was this article helpful?
Ready to try it? Start a free comparison →
Alex Chen
Senior Software Engineer
Alex Chen writes about developer tools, software engineering best practices, and productivity for the DiffChecker Pro blog. With extensive experience in software development, Alex focuses on practical guides that help developers work more effectively.