allOf — Combining Multiple Schemas
Use allOf in JSON Schema to combine multiple schemas that must all be satisfied. Learn schema composition for mixins, inheritance, and layered validation.
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"allOf": [
{
"properties": {
"id": { "type": "integer", "minimum": 1 },
"createdAt": { "type": "string", "format": "date-time" },
"updatedAt": { "type": "string", "format": "date-time" }
},
"required": ["id", "createdAt", "updatedAt"]
},
{
"properties": {
"title": { "type": "string", "minLength": 1, "maxLength": 200 },
"content": { "type": "string", "maxLength": 50000 },
"status": { "type": "string", "enum": ["draft", "published", "archived"] }
},
"required": ["title", "status"]
}
]
}Test Data
{
"id": 42,
"createdAt": "2025-01-15T10:30:00Z",
"updatedAt": "2025-01-20T14:00:00Z",
"title": "Getting Started with JSON Schema",
"content": "JSON Schema is a powerful tool for validating JSON data...",
"status": "published"
}Detailed Explanation
allOf — Every Schema Must Match
The allOf keyword validates that a value matches all of the provided sub-schemas simultaneously. This is the JSON Schema equivalent of logical AND — every constraint from every sub-schema applies.
Basic Syntax
{
"allOf": [
{ "type": "string", "minLength": 3 },
{ "pattern": "^[A-Z]" }
]
}
The value must be a string of at least 3 characters that starts with an uppercase letter. Both constraints must be satisfied.
How the Example Schema Works
The schema uses allOf to compose a blog post schema from two independent schemas:
Schema 1 — Base record fields:
id(required integer),createdAt(required date-time),updatedAt(required date-time)- These fields are common to all database records.
Schema 2 — Post-specific fields:
title(required, 1-200 characters),content(optional, up to 50,000 characters),status(required enum)- These fields are specific to blog posts.
The allOf merges both schemas: the final object must have all five required fields (id, createdAt, updatedAt, title, status) and all property constraints apply.
The test data passes because every field satisfies the combined requirements from both sub-schemas.
Use Case: Schema Mixins
allOf enables a mixin or inheritance pattern where you define reusable schema fragments and combine them:
{
"$defs": {
"Timestamped": {
"properties": {
"createdAt": { "type": "string", "format": "date-time" },
"updatedAt": { "type": "string", "format": "date-time" }
},
"required": ["createdAt", "updatedAt"]
},
"SoftDeletable": {
"properties": {
"deletedAt": { "type": ["string", "null"], "format": "date-time" }
}
}
},
"allOf": [
{ "$ref": "#/$defs/Timestamped" },
{ "$ref": "#/$defs/SoftDeletable" },
{ "properties": { "name": { "type": "string" } } }
]
}
This composes three independent concerns into a single schema — timestamps, soft deletion, and the entity-specific name property.
Conflicting Constraints
Be careful: if two sub-schemas define conflicting constraints, the combined schema may become unsatisfiable:
{
"allOf": [
{ "type": "string" },
{ "type": "integer" }
]
}
No value can be both a string and an integer, so this schema rejects everything. Always verify that your allOf sub-schemas are compatible.
allOf vs. Spreading Properties
You could achieve similar results by listing all properties in a single flat schema. The advantage of allOf is reusability — define each concern once and compose them in multiple schemas throughout your API.
Use Case
Use allOf to build layered API schemas from reusable fragments: base record fields (id, timestamps), audit fields (createdBy, modifiedBy), and entity-specific fields. This is the standard pattern for schema composition in OpenAPI specifications and large-scale API design.