JSON Schema Validation — Validate JSON Structure and Types
JSON Schema defines the structure and types your JSON must conform to. Here's how to write JSON Schema definitions, validate JSON in JavaScript and Python, and handle common...
JSON Schema is a vocabulary for describing the structure, types, and constraints of JSON data. Validating JSON against a schema catches malformed API payloads, configuration errors, and data quality issues before they cause runtime failures.
Use the JSON Formatter to validate and inspect JSON documents.
Basic JSON Schema structure
A JSON Schema is itself a JSON document with $schema, type, and constraint keywords:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "User",
"description": "A user account",
"type": "object",
"required": ["id", "name", "email"],
"properties": {
"id": {
"type": "integer",
"description": "Unique user identifier",
"minimum": 1
},
"name": {
"type": "string",
"minLength": 1,
"maxLength": 100
},
"email": {
"type": "string",
"format": "email"
},
"age": {
"type": "integer",
"minimum": 0,
"maximum": 150
},
"role": {
"type": "string",
"enum": ["admin", "user", "moderator"]
},
"tags": {
"type": "array",
"items": { "type": "string" },
"uniqueItems": true
},
"active": {
"type": "boolean",
"default": true
}
},
"additionalProperties": false
}
Valid JSON:
{ "id": 1, "name": "Alice", "email": "alice@example.com", "role": "admin" }
Invalid (missing required email):
{ "id": 1, "name": "Alice" }
Invalid (extra property not in schema):
{ "id": 1, "name": "Alice", "email": "alice@example.com", "unknown_field": true }
Type keywords
{ "type": "string" }
{ "type": "number" } // Includes integers and floats
{ "type": "integer" } // Whole numbers only
{ "type": "boolean" }
{ "type": "null" }
{ "type": "array" }
{ "type": "object" }
{ "type": ["string", "null"] } // Multiple allowed types
String constraints
{
"type": "string",
"minLength": 1,
"maxLength": 255,
"pattern": "^[a-zA-Z0-9_-]+$", // Regex pattern
"format": "email" // Semantic format
}
Format keywords:
"email"— valid email address"date"— YYYY-MM-DD"date-time"— ISO 8601 datetime"uri"— valid URI"uuid"— UUID format"ipv4"— IPv4 address"ipv6"— IPv6 address
Note: Format validation is optional in most validators (opt-in).
Number constraints
{
"type": "number",
"minimum": 0,
"maximum": 100,
"exclusiveMinimum": 0, // > 0, not >= 0
"exclusiveMaximum": 100, // < 100, not <= 100
"multipleOf": 5 // Must be divisible by 5
}
Array constraints
{
"type": "array",
"items": { "type": "string" }, // All items must be strings
"minItems": 1,
"maxItems": 10,
"uniqueItems": true // No duplicates
}
// Tuple validation (different schema per position):
{
"type": "array",
"prefixItems": [
{ "type": "number" }, // First item: number
{ "type": "string" }, // Second item: string
{ "type": "boolean" } // Third item: boolean
],
"items": false // No additional items allowed
}
Conditional schemas
{
"type": "object",
"properties": {
"type": { "type": "string", "enum": ["personal", "business"] },
"company_name": { "type": "string" }
},
"if": {
"properties": { "type": { "const": "business" } }
},
"then": {
"required": ["company_name"] // Required if type = "business"
},
"else": {
"properties": { "company_name": false } // Not allowed if type = "personal"
}
}
Reusable schemas with $ref
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$defs": {
"address": {
"type": "object",
"required": ["street", "city"],
"properties": {
"street": { "type": "string" },
"city": { "type": "string" },
"zip": { "type": "string", "pattern": "^[0-9]{5}$" }
}
}
},
"type": "object",
"properties": {
"name": { "type": "string" },
"billing_address": { "$ref": "#/$defs/address" },
"shipping_address": { "$ref": "#/$defs/address" }
}
}
Validation in JavaScript (ajv)
npm install ajv
import Ajv from 'ajv';
import addFormats from 'ajv-formats';
const ajv = new Ajv({ allErrors: true }); // Report all errors, not just first
addFormats(ajv); // Add format validation (email, date, uri, etc.)
const schema = {
type: 'object',
required: ['name', 'email'],
properties: {
name: { type: 'string', minLength: 1 },
email: { type: 'string', format: 'email' },
age: { type: 'integer', minimum: 0 },
},
additionalProperties: false,
};
const validate = ajv.compile(schema);
// Valid data:
const validData = { name: 'Alice', email: 'alice@example.com', age: 30 };
if (!validate(validData)) {
console.error(validate.errors);
} else {
console.log('Valid!');
}
// Invalid data:
const invalidData = { name: '', email: 'not-an-email', extra: 'field' };
validate(invalidData);
console.log(validate.errors);
/*
[
{ instancePath: '/name', message: 'must NOT have fewer than 1 characters' },
{ instancePath: '/email', message: 'must match format "email"' },
{ instancePath: '', message: 'must NOT have additional properties' }
]
*/
Validation in Python (jsonschema)
pip install jsonschema
from jsonschema import validate, ValidationError, Draft7Validator
schema = {
"type": "object",
"required": ["name", "email"],
"properties": {
"name": {"type": "string", "minLength": 1},
"email": {"type": "string", "format": "email"},
"age": {"type": "integer", "minimum": 0},
},
"additionalProperties": False,
}
# Simple validation (raises on first error):
try:
validate(instance={"name": "Alice", "email": "alice@example.com"}, schema=schema)
print("Valid!")
except ValidationError as e:
print(f"Error: {e.message}")
# All errors (Draft7Validator):
validator = Draft7Validator(schema)
data = {"name": "", "email": "not-email", "extra": True}
errors = list(validator.iter_errors(data))
for error in errors:
print(f"{error.json_path}: {error.message}")
API input validation pattern
// Express.js middleware using JSON Schema:
import Ajv from 'ajv';
import addFormats from 'ajv-formats';
const ajv = new Ajv({ allErrors: true });
addFormats(ajv);
function validateBody(schema) {
const validate = ajv.compile(schema);
return (req, res, next) => {
if (!validate(req.body)) {
return res.status(400).json({
error: 'Validation failed',
details: validate.errors.map(e => ({
field: e.instancePath || 'body',
message: e.message,
})),
});
}
next();
};
}
const createUserSchema = {
type: 'object',
required: ['name', 'email'],
properties: {
name: { type: 'string', minLength: 1, maxLength: 100 },
email: { type: 'string', format: 'email' },
},
additionalProperties: false,
};
app.post('/users', validateBody(createUserSchema), (req, res) => {
// req.body is guaranteed to match the schema here
});
Related tools
- JSON Formatter — validate and format JSON
- JSON Validator Online — JSON validation guide
- Common JSON Validation Errors — fix JSON errors
Related posts
- What Is JSON and Why You Should Always Format It — JSON is the universal data format of the modern web. This is what it actually is…
- The 10 Most Common JSON Validation Errors (and How to Fix Them) — Every JSON parse error in production traces back to one of ten root causes. This…
- JSON Beautifier — Format and Prettify JSON Instantly — A JSON beautifier adds proper indentation and line breaks to minified JSON, maki…
- JSON Validator Online — Validate JSON Syntax and Structure — A JSON validator checks whether your JSON is syntactically correct and tells you…
Related tool
Format, validate, and beautify JSON online. 100% client-side — your data never leaves your browser.
Written by Mian Ali Khalid. Part of the Data & Format pillar.