← Back to Blog

How to Validate JSON Against a Schema (JSON Schema Guide)

Published on February 10, 2026

What Is JSON Schema?

JSON Schema is a vocabulary that allows you to annotate and validate JSON documents. Think of it as a contract that describes the expected shape of your data: which fields must be present, what types they should be, what values are acceptable, and how nested objects and arrays should be structured. Just as TypeScript adds type safety to JavaScript, JSON Schema adds type safety to any JSON data.

The specification is itself written in JSON, which means your schema is both human-readable and machine-parseable. A validator takes two inputs — a JSON document and a JSON Schema — and returns a list of validation errors, or confirms that the document is valid. This makes JSON Schema invaluable for API development, configuration management, form validation, and data pipeline integrity checks.

JSON Schema has evolved through several drafts. The most widely adopted version is Draft-07 (also called draft-handrews-json-schema-validation-01), which strikes a good balance between features and ecosystem support. Draft 2019-09 and Draft 2020-12 add advanced features like vocabulary definitions, dynamic references, and prefixItems, but Draft-07 remains the safest choice for broad compatibility across programming languages and tools.

Core Schema Keywords

Every JSON Schema uses a set of keywords to define constraints. Understanding these core keywords is essential for writing effective schemas. Let us walk through each one with examples.

type

The type keyword restricts the JSON value to a specific data type. The six primitive types are string, number, integer, boolean, null, and the two structural types are object and array. You can also allow multiple types using an array.

{ "type": "string" }           // Only allows string values
{ "type": "integer" }          // Only allows whole numbers
{ "type": ["string", "null"] } // Allows string or null (nullable string)

properties and required

For objects, properties defines the expected keys and the schema for each key's value. The required keyword is an array of property names that must be present. Properties not listed in required are optional by default.

{
  "type": "object",
  "properties": {
    "name": { "type": "string" },
    "email": { "type": "string", "format": "email" },
    "age": { "type": "integer", "minimum": 0 }
  },
  "required": ["name", "email"]
}

In this schema, a JSON object must have name and email as strings, and age is an optional non-negative integer. An object like {"name": "Alice", "email": "alice@example.com"} is valid, while {"name": "Alice"} would fail because email is missing.

items (Array Validation)

The items keyword defines the schema that each element of an array must satisfy. You can also use minItems and maxItems to constrain array length, and uniqueItems to require that all elements are distinct.

{
  "type": "array",
  "items": {
    "type": "object",
    "properties": {
      "id": { "type": "integer" },
      "tag": { "type": "string" }
    },
    "required": ["id", "tag"]
  },
  "minItems": 1,
  "uniqueItems": true
}

This schema validates an array of tag objects. Each element must be an object with an integer id and a string tag. The array must have at least one element and no duplicates.

enum and const

The enum keyword restricts a value to a fixed set of allowed values. The const keyword restricts it to a single exact value. These are useful for status fields, configuration options, and any value that should come from a predefined list.

{
  "type": "object",
  "properties": {
    "status": {
      "type": "string",
      "enum": ["pending", "active", "suspended", "deleted"]
    },
    "version": {
      "const": "1.0"
    }
  }
}

String Validation Keywords

Strings support several validation keywords beyond type:

  • minLength / maxLength — constrain the string length
  • pattern — validate against a regular expression
  • format — semantic validation for common formats like email, uri, date-time, ipv4, uuid, and others
{
  "type": "string",
  "minLength": 8,
  "maxLength": 128,
  "pattern": "^(?=.*[A-Z])(?=.*[0-9])",
  "format": "password"
}

A Complete Example: API Request Validation

Let us build a realistic JSON Schema for a user registration API endpoint. The API expects a POST body with user details, and we want to validate it before processing:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "UserRegistration",
  "description": "Schema for the POST /api/users registration endpoint",
  "type": "object",
  "properties": {
    "username": {
      "type": "string",
      "minLength": 3,
      "maxLength": 30,
      "pattern": "^[a-zA-Z0-9_-]+$",
      "description": "Alphanumeric username with underscores and hyphens"
    },
    "email": {
      "type": "string",
      "format": "email",
      "description": "Valid email address"
    },
    "password": {
      "type": "string",
      "minLength": 8,
      "maxLength": 128,
      "description": "Password with at least 8 characters"
    },
    "plan": {
      "type": "string",
      "enum": ["free", "pro", "enterprise"],
      "default": "free"
    },
    "tags": {
      "type": "array",
      "items": { "type": "string", "maxLength": 50 },
      "maxItems": 10,
      "uniqueItems": true,
      "default": []
    },
    "profile": {
      "type": "object",
      "properties": {
        "displayName": { "type": "string", "maxLength": 100 },
        "bio": { "type": "string", "maxLength": 500 },
        "website": { "type": "string", "format": "uri" }
      },
      "additionalProperties": false
    }
  },
  "required": ["username", "email", "password"],
  "additionalProperties": false
}

Now let us test it with a valid JSON document and an invalid one:

// VALID — passes all constraints
{
  "username": "alice_dev",
  "email": "alice@example.com",
  "password": "secureP4ss!",
  "plan": "pro",
  "tags": ["developer", "react"],
  "profile": {
    "displayName": "Alice",
    "bio": "Full-stack developer",
    "website": "https://alice.dev"
  }
}

// INVALID — multiple violations
{
  "username": "al",
  "email": "not-an-email",
  "password": "short",
  "plan": "premium",
  "tags": ["developer", "developer"],
  "extraField": true
}

// Validation errors:
// 1. username: minLength 3, got 2
// 2. email: not a valid email format
// 3. password: minLength 8, got 5
// 4. plan: "premium" not in enum ["free", "pro", "enterprise"]
// 5. tags: uniqueItems violation (duplicate "developer")
// 6. extraField: additionalProperties not allowed

Using JSON Schema in Your Application

JSON Schema validation libraries exist for every major programming language. Here are the most popular options and how to use them:

JavaScript / TypeScript (Ajv)

Ajv (Another JSON Validator) is the fastest JSON Schema validator for JavaScript. It compiles schemas into optimized validation functions for maximum performance:

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

const ajv = new Ajv({ allErrors: true });
addFormats(ajv); // Adds "email", "uri", "date-time", etc.

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: "al", email: "bad" };

if (!validate(data)) {
  console.log(validate.errors);
  // [
  //   { keyword: "minLength", dataPath: "/username", ... },
  //   { keyword: "format", dataPath: "/email", ... }
  // ]
}

Python (jsonschema)

The jsonschema library is the reference implementation for Python:

import jsonschema

schema = {
    "type": "object",
    "properties": {
        "username": {"type": "string", "minLength": 3},
        "email": {"type": "string", "format": "email"},
    },
    "required": ["username", "email"],
}

data = {"username": "al", "email": "bad"}

validator = jsonschema.Draft7Validator(schema)
errors = list(validator.iter_errors(data))

for error in errors:
    print(f"{error.json_path}: {error.message}")
# $.username: 'al' is too short
# $.email: 'bad' is not a 'email'

Advanced Keywords

Beyond the core keywords, JSON Schema provides powerful composition and conditional keywords for complex validation scenarios:

  • allOf — the data must be valid against all of the given subschemas. Commonly used for combining multiple constraints or implementing schema inheritance.
  • anyOf — the data must be valid against at least one of the given subschemas. Useful for union types.
  • oneOf — the data must be valid against exactly one subschema. Useful for discriminated unions where only one variant should match.
  • not — the data must not be valid against the given subschema. Useful for excluding specific patterns.
  • if / then / else — conditional validation based on whether the data matches a condition. For example, if the country is "US" then require a zip code field with a 5-digit pattern.
  • $ref — references another schema by URI, enabling schema reuse and modular composition. You can define common types in a definitions block and reference them throughout your schema.
  • additionalProperties — when set to false, disallows any properties not explicitly listed in properties. This is critical for API validation where unknown fields should be rejected.

Here is an example using $ref and conditional validation:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "definitions": {
    "address": {
      "type": "object",
      "properties": {
        "street": { "type": "string" },
        "city": { "type": "string" },
        "country": { "type": "string" }
      },
      "required": ["street", "city", "country"]
    }
  },
  "type": "object",
  "properties": {
    "shippingAddress": { "$ref": "#/definitions/address" },
    "billingAddress": { "$ref": "#/definitions/address" },
    "sameAsShipping": { "type": "boolean" }
  },
  "if": {
    "properties": { "sameAsShipping": { "const": false } }
  },
  "then": {
    "required": ["shippingAddress", "billingAddress"]
  },
  "else": {
    "required": ["shippingAddress"]
  }
}

How to Use the PulpMiner JSON Schema Validator

The JSON Schema Validator lets you test schemas and data interactively:

  1. Paste your JSON Schema into the schema editor on the left. The tool validates that your schema itself is well-formed JSON.
  2. Paste your JSON data into the data editor on the right. This is the document you want to validate against the schema.
  3. Click Validate to run the validation. The tool reports all errors with their JSON paths and descriptions, so you know exactly which fields fail and why.
  4. Iterate and fix. Adjust your schema or data and re-validate instantly. The tool supports Draft-07 and is ideal for developing and debugging schemas before integrating them into your codebase.

Best Practices for JSON Schema

  • Start with required fields only. Define the minimum viable schema first, then add constraints incrementally. An overly strict schema is harder to maintain and breaks more often when the API evolves.
  • Use additionalProperties: false for API request validation. This catches typos in field names and prevents unexpected data from entering your system.
  • Add descriptions to every field. Schemas serve as documentation. A well-annotated schema is often more useful than a separate API documentation page.
  • Use $ref for reusable types. Define common structures like addresses, pagination parameters, and error responses once in a definitions block and reference them throughout your schemas.
  • Version your schemas. When your API changes, update the schema and document which version of the schema corresponds to which API version. Store schemas in version control alongside your code.
  • Test schemas with edge cases. Validate empty objects, null values, empty arrays, extremely long strings, and negative numbers. Schema bugs are often found at the boundaries.

JSON Schema is one of the most powerful tools in a developer's toolkit for ensuring data integrity. Whether you are building a public API, processing webhook payloads, or validating configuration files, a well-crafted schema catches bugs before they reach production.

Ready to validate? Try the JSON Schema Validator — free, instant, and completely client-side.

Need to extract data from websites?

PulpMiner turns any webpage into a structured JSON API. No scraping code needed — just point, click, and get clean data.

Try PulpMiner Free

No credit card required