ToolHub
查看所有文章

JSON Schema Validation Guide: Validate Your Data Structure

Every application that receives data from external sources faces the same fundamental question: can I trust this data? Whether it is an API request body, a configuration file, a message from a queue, or a data import, untrusted data must be validated before it enters your system. JSON Schema provides a standardized, language-independent way to define what valid data looks like and to verify that incoming data conforms to that definition. This guide covers everything from writing your first schema to advanced patterns for complex validation, with practical examples you can apply immediately.

What Is JSON Schema?

JSON Schema is a JSON document that describes the structure and constraints of other JSON documents. It is a vocabulary that allows you to annotate and validate JSON data, standardized through the Internet Engineering Task Force (IETF). A JSON Schema defines rules about what fields must exist, what types they must be, what values are acceptable, and how objects and arrays should be structured.

Think of JSON Schema as a contract for your data. Just as a database schema defines the columns, types, and constraints of a table, a JSON Schema defines the properties, types, and constraints of a JSON document. Any JSON data that satisfies all the constraints in a schema is called a valid instance, while data that violates any constraint is invalid.

What JSON Schema Is Not

JSON Schema Versions

JSON Schema has evolved through several drafts, each adding features and refining the vocabulary. Understanding the versions helps you choose the right one for your project and avoid compatibility issues.

Version $schema URI Status Key Features
Draft 2020-12 https://json-schema.org/draft/2020-12/schema Current prefixItems, dynamicRef, vocabulary support
Draft 2019-09 https://json-schema.org/draft/2019-09/schema Stable unevaluatedProperties, $recursiveRef
Draft 7 http://json-schema.org/draft-07/schema# Widely supported if/then/else, contentEncoding
Draft 6 http://json-schema.org/draft-06/schema# Legacy propertyNames, contains
Draft 4 http://json-schema.org/draft-04/schema# Deprecated Original widely-adopted version
Recommendation: Use Draft 2020-12 for new projects. It is the latest stable version with the most features and is supported by major validation libraries. If you need maximum compatibility with existing tools, Draft 7 is a safe choice. Avoid Draft 4 and earlier.

Writing Your First Schema

Let us start with a simple example: a schema for a user object with a name, email, and age.

{
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "$id": "https://example.com/schemas/user.json",
    "title": "User",
    "description": "A user account in the system",
    "type": "object",
    "properties": {
        "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "description": "The user's full name"
        },
        "email": {
            "type": "string",
            "format": "email",
            "description": "The user's email address"
        },
        "age": {
            "type": "integer",
            "minimum": 0,
            "maximum": 150,
            "description": "The user's age in years"
        }
    },
    "required": ["name", "email"],
    "additionalProperties": false
}

This schema declares that a valid user must be an object with name and email as required string properties. The age property is optional but must be an integer between 0 and 150 if present. The additionalProperties: false constraint prevents any properties not defined in the schema, which catches typos and unexpected fields.

Core Keywords Reference

JSON Schema provides a rich vocabulary of keywords for defining constraints. Here are the most important ones organized by category.

Type Keywords

Keyword Description Example
type Expected data type(s) "type": "string" or "type": ["string", "null"]
enum List of allowed values "enum": ["active", "inactive", "pending"]
const Must equal this exact value "const": "v2"

Number Constraints

Keyword Description Example
minimum Minimum value (inclusive) "minimum": 0
exclusiveMinimum Minimum value (exclusive) "exclusiveMinimum": 0
maximum Maximum value (inclusive) "maximum": 100
exclusiveMaximum Maximum value (exclusive) "exclusiveMaximum": 100
multipleOf Must be a multiple of this value "multipleOf": 0.01

String Constraints

Keyword Description Example
minLength Minimum string length "minLength": 1
maxLength Maximum string length "maxLength": 255
pattern Regex pattern the string must match "pattern": "^[A-Z]{2}\\d{4}$"
format Semantic format (email, uri, date-time, etc.) "format": "email"

Object Constraints

Keyword Description Example
properties Schema for each known property "properties": {"name": {"type": "string"}}
required List of mandatory properties "required": ["name", "email"]
additionalProperties Whether extra properties are allowed "additionalProperties": false
minProperties Minimum number of properties "minProperties": 1
maxProperties Maximum number of properties "maxProperties": 10
patternProperties Schemas for properties matching a regex "patternProperties": {"^S_": {"type": "string"}}

Array Constraints

Keyword Description Example
items Schema for all array items "items": {"type": "string"}
prefixItems Schemas for positional items (Draft 2020-12) "prefixItems": [{"type": "string"}, {"type": "number"}]
minItems Minimum number of items "minItems": 1
maxItems Maximum number of items "maxItems": 100
uniqueItems All items must be unique "uniqueItems": true

Common Schema Patterns

Real-world schemas often require patterns beyond simple type checking. Here are the most frequently needed patterns.

Conditional Validation with if/then/else

Use conditional logic to apply different constraints based on the value of a property. For example, a payment object requires different fields depending on the payment method.

{
    "type": "object",
    "properties": {
        "method": { "enum": ["credit_card", "bank_transfer"] },
        "card_number": { "type": "string" },
        "routing_number": { "type": "string" }
    },
    "required": ["method"],
    "if": {
        "properties": { "method": { "const": "credit_card" } }
    },
    "then": {
        "required": ["card_number"]
    },
    "else": {
        "required": ["routing_number"]
    }
}

Composition with allOf, anyOf, oneOf

Composition keywords allow you to combine schemas in powerful ways:

{
    "oneOf": [
        {
            "type": "object",
            "properties": {
                "type": { "const": "email" },
                "address": { "type": "string", "format": "email" }
            },
            "required": ["type", "address"]
        },
        {
            "type": "object",
            "properties": {
                "type": { "const": "phone" },
                "number": { "type": "string", "pattern": "^\\+?[1-9]\\d{1,14}$" }
            },
            "required": ["type", "number"]
        }
    ]
}

Reusing Schemas with $ref

The $ref keyword allows you to reference and reuse schemas, eliminating duplication and keeping your schemas maintainable. You can reference schemas within the same document or external files.

{
    "$id": "https://example.com/schemas/order.json",
    "type": "object",
    "properties": {
        "customer": { "$ref": "#/$defs/address" },
        "shipping": { "$ref": "#/$defs/address" },
        "billing": { "$ref": "#/$defs/address" },
        "items": {
            "type": "array",
            "items": { "$ref": "#/$defs/lineItem" },
            "minItems": 1
        }
    },
    "required": ["customer", "items"],
    "$defs": {
        "address": {
            "type": "object",
            "properties": {
                "street": { "type": "string" },
                "city": { "type": "string" },
                "zip": { "type": "string", "pattern": "^\\d{5}(-\\d{4})?$" },
                "country": { "type": "string", "minLength": 2, "maxLength": 2 }
            },
            "required": ["street", "city", "zip", "country"]
        },
        "lineItem": {
            "type": "object",
            "properties": {
                "product": { "type": "string" },
                "quantity": { "type": "integer", "minimum": 1 },
                "price": { "type": "number", "exclusiveMinimum": 0 }
            },
            "required": ["product", "quantity", "price"]
        }
    }
}

Nullable Types

In JSON Schema Draft 2020-12, nullable types are expressed using an array of types that includes "null":

{
    "type": ["string", "null"],
    "description": "An optional display name, or null if not set"
}

In older drafts, the nullable: true keyword was used in OpenAPI specifications. For standard JSON Schema, always use the type array approach.

Format Validation

The format keyword provides semantic validation beyond structural checks. It specifies that a string must conform to a well-known format. Commonly supported formats include:

Format Description Example
email Email address user@example.com
uri Valid URI https://example.com/path
uri-reference URI or relative reference /path/to/resource
date-time ISO 8601 date-time 2026-05-19T14:30:00Z
date ISO 8601 date 2026-05-19
time ISO 8601 time 14:30:00Z
ipv4 IPv4 address 192.168.1.1
ipv6 IPv6 address ::1
uuid Universally unique identifier 550e8400-e29b-41d4-a716-446655440000
hostname Internet hostname www.example.com
Important: By default, the format keyword is an annotation, not a constraint. Validators may ignore it unless you explicitly enable format validation. In Ajv, pass { strict: true } or { validateFormats: true } to enforce format checking. Always verify that your validator enforces format constraints.

Validating JSON Data Programmatically

Schema validation is most useful when integrated into your application code. Here are examples using popular libraries in different languages.

JavaScript with Ajv

Ajv is the most widely used JSON Schema validator for JavaScript. It supports all draft versions and offers excellent performance through JIT compilation of schemas.

import Ajv from 'ajv';
import addFormats from 'ajv-formats';

const ajv = new Ajv();
addFormats(ajv);

const schema = {
    type: 'object',
    properties: {
        name: { type: 'string', minLength: 1 },
        email: { type: 'string', format: 'email' },
        age: { type: 'integer', minimum: 0 }
    },
    required: ['name', 'email'],
    additionalProperties: false
};

const validate = ajv.compile(schema);
const valid = validate({ name: 'Alice', email: 'alice@example.com', age: 30 });

if (!valid) {
    console.log(validate.errors);
    // [{ keyword: 'required', params: { missingProperty: 'email' }, ... }]
}

Python with jsonschema

from jsonschema import validate, ValidationError

schema = {
    "type": "object",
    "properties": {
        "name": {"type": "string", "minLength": 1},
        "email": {"type": "string", "format": "email"},
        "age": {"type": "integer", "minimum": 0}
    },
    "required": ["name", "email"],
    "additionalProperties": False
}

try:
    validate(instance={"name": "Alice", "email": "alice@example.com"}, schema=schema)
except ValidationError as e:
    print(f"Validation failed: {e.message}")

API Data Validation with JSON Schema

One of the most valuable applications of JSON Schema is validating API request and response data. This ensures that your API receives well-formed input and returns data in the expected format, catching errors early and providing clear error messages to clients.

Express.js Middleware

import Ajv from 'ajv';

const ajv = new Ajv({ allErrors: true });

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
            });
        }
        next();
    };
}

app.post('/api/users',
    validateBody({
        type: 'object',
        properties: {
            name: { type: 'string', minLength: 1, maxLength: 100 },
            email: { type: 'string', format: 'email' },
            role: { enum: ['admin', 'editor', 'viewer'] }
        },
        required: ['name', 'email'],
        additionalProperties: false
    }),
    (req, res) => {
        // req.body is guaranteed valid here
        createUser(req.body);
    }
);

OpenAPI and JSON Schema

OpenAPI (formerly Swagger) uses a subset of JSON Schema for defining API request and response schemas. If you are already using OpenAPI, you can extract the schemas from your API specification and use them for runtime validation. Tools like openapi-schema-validator and express-openapi-validator automate this process, ensuring that your API documentation and validation logic always stay in sync.

Best Practices

Need to validate JSON data against a schema? Try our free online JSON Schema Validator. Paste your schema and data to get instant validation results with detailed error messages.

JSON Schema Validator JSON Formatter

Frequently Asked Questions

What is JSON Schema?

JSON Schema is a JSON document that describes the structure and constraints of other JSON documents. It lets you define required fields, expected data types, value ranges, string patterns, and nested object structures. You can use it to validate incoming data, generate documentation, and create form interfaces automatically.

What version of JSON Schema should I use?

Use JSON Schema Draft 2020-12 for new projects. It is the latest stable version and is supported by major validation libraries like Ajv. Draft 7 is also widely supported if you need compatibility with older tools. Avoid Draft 4 and earlier as they use outdated keywords and lack modern features.

How is JSON Schema different from TypeScript interfaces?

TypeScript interfaces provide compile-time type checking within TypeScript code only. JSON Schema provides runtime validation that works across programming languages and can validate data from any source (API requests, files, databases). Use TypeScript for development-time safety and JSON Schema for runtime data validation at system boundaries.

Can JSON Schema validate API request bodies?

Yes, JSON Schema is widely used for API request and response validation. Frameworks like Express (with express-json-validator), FastAPI, and Spring Boot support JSON Schema validation natively or through middleware. Validating request bodies against a schema ensures that incoming data has the correct structure before your application processes it.

What are the most important JSON Schema keywords?

The most essential keywords are: type (data type), properties (object fields), required (mandatory fields), items (array element schema), minimum/maximum (number bounds), minLength/maxLength (string bounds), pattern (regex for strings), enum (allowed values), and $ref (reference to reuse schemas). These cover the vast majority of validation needs.