jsonschemavalidationapitutorial

JSON Schema Validation: Complete Guide with Examples

·10 min read

What Is JSON Schema?

JSON Schema is a vocabulary for describing and validating the structure of JSON data. A JSON Schema is itself a JSON document that specifies what a valid JSON instance must look like — which fields are required, what types they must be, what values are allowed, minimum and maximum lengths, and more.

Think of it as a contract between a data producer and a data consumer. If your API produces JSON that matches a published schema, any client that validates against the same schema knows exactly what to expect — no surprises, no runtime crashes.

JSON Schema is defined by an open standard. The current version is 2020-12.

Basic Schema Structure

An empty schema `{}` allows any valid JSON. A schema that requires the value to be a string:

json
{ "type": "string" }

A schema for a user object with required fields and type constraints:

json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "User",
  "type": "object",
  "required": ["id", "name", "email"],
  "properties": {
    "id":    { "type": "integer" },
    "name":  { "type": "string",  "minLength": 1, "maxLength": 100 },
    "email": { "type": "string",  "format": "email" },
    "age":   { "type": "integer", "minimum": 0, "maximum": 120 }
  },
  "additionalProperties": false
}

Setting additionalProperties to false means any key not listed in properties will cause validation to fail. This is strict mode — useful for API request bodies where you want to reject unexpected fields.

JSON Schema Types

The type keyword accepts these values: string, number, integer, boolean, object, array, and null.

Use integer instead of number when decimals are not allowed. You can also allow multiple types: `"type": ["string", "null"]` for a nullable string.

String Constraints

json
{
  "type": "string",
  "minLength": 2,
  "maxLength": 50,
  "pattern": "^[A-Za-z0-9_]+$"
}

The pattern property takes a regular expression. The format keyword validates well-known formats: email, uri, date, date-time, ipv4, uuid. Note that format validation is opt-in — validators must be configured to enforce it.

Number Constraints

json
{
  "type": "number",
  "minimum": 0,
  "maximum": 100,
  "multipleOf": 0.5,
  "exclusiveMinimum": 0
}

Use exclusiveMinimum instead of minimum when the boundary value itself is not allowed (value must be greater than 0, not greater than or equal to 0).

Enum — Restricting to Specific Values

The enum keyword restricts a value to a fixed list of allowed values:

json
{
  "type": "string",
  "enum": ["pending", "active", "suspended", "deleted"]
}

This works for any type — enum can contain a mix of types: numbers, strings, booleans, and null.

Object Properties and Required Fields

json
{
  "type": "object",
  "required": ["productId", "quantity"],
  "properties": {
    "productId": { "type": "string" },
    "quantity":  { "type": "integer", "minimum": 1 },
    "note":      { "type": "string",  "maxLength": 500 }
  }
}

Only productId and quantity are required — note is optional. If note is present, it must be a string of at most 500 characters.

Array Validation

json
{
  "type": "array",
  "minItems": 1,
  "maxItems": 100,
  "uniqueItems": true,
  "items": {
    "type": "string",
    "minLength": 1
  }
}

The items keyword defines the schema that every element of the array must match.

Nested Objects

json
{
  "type": "object",
  "properties": {
    "billing": {
      "type": "object",
      "required": ["street", "city", "country"],
      "properties": {
        "street":  { "type": "string" },
        "city":    { "type": "string" },
        "state":   { "type": "string" },
        "pincode": { "type": "string", "pattern": "^[0-9]{6}$" },
        "country": { "type": "string", "minLength": 2, "maxLength": 2 }
      }
    }
  }
}

Real-World Example: Order Schema

json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Order",
  "type": "object",
  "required": ["orderId", "userId", "items", "status", "createdAt"],
  "properties": {
    "orderId":     { "type": "string" },
    "userId":      { "type": "integer" },
    "status":      { "type": "string", "enum": ["pending", "confirmed", "shipped", "delivered", "cancelled"] },
    "totalAmount": { "type": "number", "minimum": 0 },
    "currency":    { "type": "string", "minLength": 3, "maxLength": 3 },
    "createdAt":   { "type": "string", "format": "date-time" },
    "items": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "object",
        "required": ["productId", "quantity", "unitPrice"],
        "properties": {
          "productId":   { "type": "string" },
          "name":        { "type": "string" },
          "quantity":    { "type": "integer", "minimum": 1 },
          "unitPrice":   { "type": "number",  "minimum": 0 },
          "discount":    { "type": "number",  "minimum": 0, "maximum": 100 }
        }
      }
    }
  }
}

A valid order document that matches this schema:

json
{
  "orderId": "ORD-20250501-001",
  "userId": 42,
  "status": "confirmed",
  "totalAmount": 1499.00,
  "currency": "INR",
  "createdAt": "2025-05-01T10:30:00Z",
  "items": [
    { "productId": "PROD-101", "name": "Mechanical Keyboard", "quantity": 1, "unitPrice": 1499.00 }
  ]
}

Validate in Node.js with Ajv

Ajv is the most popular JSON Schema validator for JavaScript and TypeScript:

javascript
import Ajv from "ajv";
import addFormats from "ajv-formats"; // for format: "email", "date-time", etc.

const ajv = new Ajv({ allErrors: true }); // collect ALL errors, not just first
addFormats(ajv);

const schema = {
  type: "object",
  required: ["name", "email"],
  properties: {
    name:  { type: "string", minLength: 1 },
    email: { type: "string", format: "email" },
  },
};

const validate = ajv.compile(schema);

const data = { name: "Ravi", email: "not-an-email" };
const valid = validate(data);

if (!valid) {
  console.error(validate.errors);
  // [{ instancePath: "/email", message: "must match format "email"" }]
}

Install with: `npm install ajv ajv-formats`

Validate in Python with jsonschema

python
import jsonschema
import json

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

data = {"name": "Ravi", "email": "ravi@example.com"}

try:
    jsonschema.validate(instance=data, schema=schema)
    print("Valid")
except jsonschema.exceptions.ValidationError as e:
    print(f"Invalid: {e.message}")
except jsonschema.exceptions.SchemaError as e:
    print(f"Schema error: {e.message}")

Install with: `pip install jsonschema[format-nongpl]`

Why Use JSON Schema?

Without schema validation, your API may accept malformed data and fail much later — during database insertion, in a payment flow, or in a report. Schema validation catches problems at the boundary — the moment data enters your system — where fixing them is cheapest and safest.

Try JSON Schema Validator

Validate JSON against a JSON Schema and see every error explained.