Introduction to JSON Schema: Validate Your Data
A practical introduction to JSON Schema for defining, documenting, and validating the structure of JSON data. From basic types to advanced composition patterns.
What Is JSON Schema?
JSON Schema is a vocabulary for annotating and validating JSON documents. Think of it as a contract or blueprint that describes what valid JSON should look like for a particular use case. It defines which fields are required, what types they should be, what ranges are acceptable, and how nested structures should be organized.
The specification is maintained at json-schema.org and is currently at Draft 2020-12. JSON Schema is used for API documentation (OpenAPI/Swagger), form generation, configuration validation, code generation, and data quality enforcement.
A Minimal Schema
A JSON Schema is itself a JSON document. The simplest useful schema defines the type of the root value:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"name": { "type": "string" },
"age": { "type": "integer" },
"email": { "type": "string" }
},
"required": ["name", "email"]
}This schema says: the data must be an object with a name (string, required), an age (integer, optional), and an email (string, required). Any JSON document that does not match these rules fails validation.
Core Type Keywords
JSON Schema recognizes six primitive types that mirror JSON's own type system, plus integer as a convenience type:
| Type | Description | Example |
|---|---|---|
| string | A JSON string | "hello" |
| number | Any JSON number (integer or float) | 3.14 |
| integer | Whole numbers only | 42 |
| boolean | true or false | true |
| null | The null value | null |
| array | An ordered list of values | [1, 2, 3] |
| object | An unordered set of key-value pairs | {"a": 1} |
Common Validation Keywords
Beyond type checking, JSON Schema provides keywords for constraining values within each type. These are the most commonly used:
String Constraints
{
"type": "string",
"minLength": 1,
"maxLength": 255,
"pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$",
"format": "email"
}The pattern keyword accepts a regular expression. The format keyword provides semantic validation for common string formats like email, date-time, uri, ipv4, ipv6, and uuid. Note that format is advisory by default; validators must opt in to enforcing it.
Number Constraints
{
"type": "number",
"minimum": 0,
"maximum": 100,
"exclusiveMinimum": 0,
"multipleOf": 0.5
}Use minimum and maximum for inclusive bounds, and exclusiveMinimum and exclusiveMaximum for exclusive bounds. The multipleOf keyword constrains the value to be a multiple of the given number, useful for currencies (multiples of 0.01) or step values.
Array Constraints
{
"type": "array",
"items": { "type": "string" },
"minItems": 1,
"maxItems": 10,
"uniqueItems": true
}The items keyword defines the schema for array elements. Use prefixItems (Draft 2020-12) for tuple validation where each position has a different schema. The uniqueItems keyword ensures no duplicates.
Object Constraints
{
"type": "object",
"properties": {
"name": { "type": "string" },
"role": { "type": "string", "enum": ["admin", "user", "guest"] }
},
"required": ["name"],
"additionalProperties": false,
"minProperties": 1,
"maxProperties": 20
}The required keyword lists which properties must be present. Setting additionalProperties to false rejects any properties not listed in properties, which is a strict validation mode useful for APIs where extra fields indicate client errors.
Composition Keywords
JSON Schema provides powerful composition keywords that let you build complex schemas from simpler ones:
- allOf: The data must be valid against all listed schemas. Used for combining multiple constraints or implementing inheritance.
- anyOf: The data must be valid against at least one of the listed schemas. Used for union types.
- oneOf: The data must be valid against exactly one of the listed schemas. Used for discriminated unions.
- not: The data must not be valid against the given schema. Used for exclusion rules.
// A field that accepts either a string or a number
{
"anyOf": [
{ "type": "string" },
{ "type": "number" }
]
}
// A response that must match exactly one of two shapes
{
"oneOf": [
{
"type": "object",
"properties": {
"status": { "const": "success" },
"data": { "type": "object" }
},
"required": ["status", "data"]
},
{
"type": "object",
"properties": {
"status": { "const": "error" },
"message": { "type": "string" }
},
"required": ["status", "message"]
}
]
}References and Reuse
The $ref keyword lets you reference other schemas, either within the same document or from external files. This is essential for avoiding duplication in large schemas:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$defs": {
"address": {
"type": "object",
"properties": {
"street": { "type": "string" },
"city": { "type": "string" },
"country": { "type": "string" }
},
"required": ["street", "city", "country"]
}
},
"type": "object",
"properties": {
"name": { "type": "string" },
"home": { "$ref": "#/$defs/address" },
"work": { "$ref": "#/$defs/address" }
}
}The $defs section (formerly definitions) holds reusable sub-schemas. The $ref keyword points to them using JSON Pointer syntax.
Schema Drafts and Versions
JSON Schema has evolved through several draft versions. The $schema keyword declares which version the schema targets:
- Draft-04: The first widely adopted version. Still used in many existing systems.
- Draft-06/07: Added
if/then/else,const, andcontainskeywords. - Draft 2019-09: Renamed
definitionsto$defs, added$anchorand vocabulary support. - Draft 2020-12: Current version. Replaced
itemsarray form withprefixItems, added$dynamicRef.
For new projects, use Draft 2020-12. For compatibility with existing tooling, check which draft your validator supports.
Validation Libraries and Tools
JSON Schema validators are available in every major language:
- JavaScript/TypeScript: Ajv (the most popular and fastest), Zod (for TypeScript-first schemas)
- Python: jsonschema, fastjsonschema
- Java: networknt/json-schema-validator, everit-org/json-schema
- Go: santhosh-tekuri/jsonschema, xeipuuv/gojsonschema
- Ruby: json_schemer
- .NET: NJsonSchema, JsonSchema.Net
Beyond validation, JSON Schema powers API documentation tools (OpenAPI/Swagger), form generators (react-jsonschema-form), and code generators (quicktype, json-schema-to-typescript).
Inferring Schemas from Existing Data
Writing schemas from scratch can be tedious for large data structures. Schema inference tools analyze existing JSON documents and generate a starting schema that you can then refine. Our JSON Formatter includes schema inference in the Schema tab. Paste any JSON document to see:
- Detected types for each field
- Which fields are required vs. optional (for arrays of objects)
- Type inconsistencies across array items
- A generated TypeScript interface you can copy into your codebase
The inferred schema serves as a starting point. You should add validation constraints (minLength, pattern, enum) based on your domain knowledge.
Practical Example: API Response Validation
Here is a realistic schema for validating a REST API response that returns a list of users. This demonstrates how multiple JSON Schema features work together:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"total": { "type": "integer", "minimum": 0 },
"page": { "type": "integer", "minimum": 1 },
"per_page": { "type": "integer", "minimum": 1, "maximum": 100 },
"users": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": { "type": "integer" },
"email": { "type": "string", "format": "email" },
"name": { "type": "string", "minLength": 1 },
"role": { "type": "string", "enum": ["admin", "user", "guest"] },
"created_at": { "type": "string", "format": "date-time" },
"is_active": { "type": "boolean" }
},
"required": ["id", "email", "name", "role"],
"additionalProperties": false
}
}
},
"required": ["total", "page", "per_page", "users"]
}This schema validates the response shape, ensures required fields are present, constrains pagination values, validates email format, restricts role to known values, and rejects unexpected fields. Integrating this validation into your API client or test suite catches regressions before they reach production.
Further Reading
- JSON Schema specification
Official JSON Schema specification and getting started guides.
- Understanding JSON Schema
Free online book explaining JSON Schema concepts step by step.
- JSON Schema Draft 2020-12
The latest IETF draft of the JSON Schema core specification.