What is JSON Schema?
JSON Schema is a powerful vocabulary for validating the structure of JSON data. It allows you to describe the expected format, data types, required fields, and constraints of your JSON documents. Think of it as a contract that defines what valid JSON looks like for your application.
JSON Schema provides a standardized way to:
- Validate JSON data before processing
- Document your JSON structure for API consumers
- Generate TypeScript/Java/Python types automatically
- Create interactive documentation
- Ensure data quality and prevent errors
Basic Schema Structure
Every JSON Schema is itself a JSON document. Here's a minimal example:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/user.schema.json",
"title": "User",
"description": "A registered user",
"type": "object",
"properties": {
"id": {
"type": "integer",
"description": "Unique user identifier"
},
"username": {
"type": "string",
"minLength": 3,
"maxLength": 20,
"pattern": "^[a-zA-Z0-9_]+$"
},
"email": {
"type": "string",
"format": "email"
},
"age": {
"type": "integer",
"minimum": 13,
"maximum": 120
}
},
"required": ["id", "username", "email"]
}
Schema Keywords Explained
- $schema: Specifies which JSON Schema version you're using
- $id: Unique identifier for the schema (URI)
- title: Human-readable schema name
- description: Documentation for the schema
- type: Data type (object, array, string, number, integer, boolean, null)
- properties: Defines object properties
- required: Array of required property names
Data Type Validation
String Validation
{
"type": "string",
"minLength": 5,
"maxLength": 100,
"pattern": "^[A-Z]",
"format": "email"
}
Common String Formats:
date-time: ISO 8601 date-time (2025-01-16T10:30:00Z)
date: Full date (2025-01-16)
time: Time (10:30:00)
email: Email address
uri: URI/URL
uuid: UUID identifier
ipv4: IPv4 address
ipv6: IPv6 address
Number Validation
{
"type": "number",
"minimum": 0,
"maximum": 100,
"exclusiveMinimum": 0,
"multipleOf": 0.01
}
Array Validation
{
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"maxItems": 10,
"uniqueItems": true
}
Object Validation
{
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"}
},
"required": ["name"],
"additionalProperties": false,
"minProperties": 1,
"maxProperties": 10
}
Advanced Schema Patterns
Combining Schemas (anyOf, allOf, oneOf)
anyOf - Must match at least one schema:
{
"anyOf": [
{"type": "string"},
{"type": "number"}
]
}
allOf - Must match all schemas (useful for inheritance):
{
"allOf": [
{
"type": "object",
"properties": {
"name": {"type": "string"}
}
},
{
"properties": {
"age": {"type": "integer"}
}
}
]
}
oneOf - Must match exactly one schema:
{
"oneOf": [
{
"properties": {
"type": {"const": "credit_card"},
"cardNumber": {"type": "string"}
}
},
{
"properties": {
"type": {"const": "bank_transfer"},
"accountNumber": {"type": "string"}
}
}
]
}
Conditional Validation (if/then/else)
{
"type": "object",
"properties": {
"country": {"type": "string"},
"postalCode": {"type": "string"}
},
"if": {
"properties": {"country": {"const": "US"}}
},
"then": {
"properties": {
"postalCode": {"pattern": "^[0-9]{5}(-[0-9]{4})?$"}
}
},
"else": {
"properties": {
"postalCode": {"pattern": "^[A-Z0-9]+$"}
}
}
}
Schema References ($ref)
Reuse schema definitions to avoid duplication:
{
"$defs": {
"address": {
"type": "object",
"properties": {
"street": {"type": "string"},
"city": {"type": "string"},
"zipCode": {"type": "string"}
}
}
},
"type": "object",
"properties": {
"billingAddress": {"$ref": "#/$defs/address"},
"shippingAddress": {"$ref": "#/$defs/address"}
}
}
Real-World Example: E-Commerce Product Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/product.schema.json",
"title": "Product",
"description": "E-commerce product schema",
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"description": "Unique product identifier"
},
"name": {
"type": "string",
"minLength": 1,
"maxLength": 200
},
"description": {
"type": "string",
"maxLength": 2000
},
"price": {
"type": "number",
"minimum": 0,
"multipleOf": 0.01
},
"currency": {
"type": "string",
"enum": ["USD", "EUR", "GBP", "JPY"]
},
"inStock": {
"type": "boolean"
},
"categories": {
"type": "array",
"items": {"type": "string"},
"minItems": 1,
"uniqueItems": true
},
"images": {
"type": "array",
"items": {
"type": "object",
"properties": {
"url": {"type": "string", "format": "uri"},
"alt": {"type": "string"},
"primary": {"type": "boolean"}
},
"required": ["url", "alt"]
}
},
"variants": {
"type": "array",
"items": {
"type": "object",
"properties": {
"sku": {"type": "string"},
"size": {"type": "string"},
"color": {"type": "string"},
"stock": {"type": "integer", "minimum": 0}
},
"required": ["sku", "stock"]
}
},
"metadata": {
"type": "object",
"properties": {
"weight": {"type": "number"},
"dimensions": {
"type": "object",
"properties": {
"length": {"type": "number"},
"width": {"type": "number"},
"height": {"type": "number"}
}
}
}
}
},
"required": ["id", "name", "price", "currency", "inStock"],
"additionalProperties": false
}
Validation in Different Languages
JavaScript (Node.js)
const Ajv = require('ajv');
const ajv = new Ajv();
const schema = {
type: 'object',
properties: {
username: { type: 'string', minLength: 3 },
email: { type: 'string', format: 'email' }
},
required: ['username', 'email']
};
const validate = ajv.compile(schema);
const data = {
username: 'john',
email: 'john@example.com'
};
const valid = validate(data);
if (!valid) {
console.log(validate.errors);
}
Python
import jsonschema
from jsonschema import validate
schema = {
"type": "object",
"properties": {
"username": {"type": "string", "minLength": 3},
"email": {"type": "string", "format": "email"}
},
"required": ["username", "email"]
}
data = {
"username": "john",
"email": "john@example.com"
}
try:
validate(instance=data, schema=schema)
print("Valid!")
except jsonschema.exceptions.ValidationError as err:
print(err)
Best Practices
1. Use $schema to Specify Version
Always include the $schema keyword to indicate which JSON Schema draft you're using. This ensures consistent validation behavior.
2. Provide Descriptive Metadata
Use title, description, and examples to document your schema thoroughly. This helps both humans and tools understand the schema.
{
"type": "string",
"title": "User Email",
"description": "Primary email address for user communication",
"format": "email",
"examples": ["user@example.com"]
}
3. Use $defs for Reusable Components
Define common patterns once and reference them throughout your schema:
{
"$defs": {
"timestamp": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp"
}
},
"properties": {
"createdAt": {"$ref": "#/$defs/timestamp"},
"updatedAt": {"$ref": "#/$defs/timestamp"}
}
}
4. Set additionalProperties Carefully
Decide whether to allow extra properties:
"additionalProperties": false - Strict validation, no extra properties allowed
"additionalProperties": true - Allow any extra properties (default)
"additionalProperties": {"type": "string"} - Extra properties must be strings
5. Use Enums for Fixed Values
{
"status": {
"type": "string",
"enum": ["pending", "processing", "completed", "failed"],
"description": "Order status"
}
}
6. Validate Early and Often
Validate data at API boundaries, not just when processing. This provides faster feedback and better error messages.
7. Version Your Schemas
As your application evolves, version your schemas to support backward compatibility:
{
"$id": "https://api.example.com/schemas/v2/user.json",
"$schema": "https://json-schema.org/draft/2020-12/schema"
}
8. Use Pattern Properties for Dynamic Keys
{
"type": "object",
"patternProperties": {
"^[a-zA-Z0-9_]+$": {
"type": "string"
}
}
}
Common Pitfalls to Avoid
- Overly Restrictive Schemas: Don't make schemas too strict initially. Allow room for evolution.
- Missing Required Fields: Forgetting to mark critical fields as required leads to incomplete data.
- Ignoring Validation Errors: Always handle and log validation errors properly.
- Not Testing Schemas: Test your schemas with both valid and invalid data.
- Deep Nesting: Avoid excessive nesting which makes schemas hard to maintain.
Tools and Resources
Recommended Tools:
- JSON Schema Validator: Try our JSON Schema Validator
- Schema Generator: Auto-generate schemas from JSON with our Schema Generator
- AJV: Fast JSON Schema validator for JavaScript/Node.js
- jsonschema (Python): Python implementation of JSON Schema
Conclusion
JSON Schema is an essential tool for building robust, production-grade applications. By validating data structure and types, you catch errors early, improve data quality, and create better documentation for your APIs. Start with basic schemas and gradually add more sophisticated validation as your needs grow.
Validate Your JSON Data
Use our professional validation tools to ensure data quality.