JSON Schema Tutorial: Validate JSON with Examples

Last updated:

JSON Schema is a JSON document that describes and validates the structure of other JSON data — a schema declares required fields, allowed types, and constraints that a value must satisfy. The current stable specification is Draft 2020-12, but Draft 07 remains the most widely supported across validator libraries; Ajv, the dominant JavaScript validator, has 100 million weekly npm downloads and supports both drafts. A schema document is identified by the $schema keyword pointing to the draft URI, and a required array listing mandatory property names; omitting required makes all properties optional regardless of whether they appear in properties. This guide covers the 7 JSON Schema types, required and properties, if/then/else conditionals, $ref for reuse, Draft 07 vs Draft 2020-12 differences, and Ajv validation in JavaScript.

What is JSON Schema?

Any JSON value can be validated against a schema: an API request body, a configuration file, or a database document. The most-used validator for JavaScript is Ajv, with over 100 million weekly npm downloads. Validators also exist for Python (jsonschema), Java (everit), Go (gojsonschema), and most other languages. JSON Schema is additionally used to auto-generate TypeScript types and power form validation libraries such as React Hook Form and Zod.

// A simple schema for a user object
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["id", "email"],
  "properties": {
    "id": { "type": "integer" },
    "email": { "type": "string", "format": "email" },
    "name": { "type": "string" }
  }
}

// Valid data:
{ "id": 1, "email": "alice@example.com", "name": "Alice" }
{ "id": 2, "email": "bob@example.com" }

// Invalid data:
{ "email": "alice@example.com" }        // missing required "id"
{ "id": "one", "email": "a@b.com" }    // id must be integer

If you need ready-made snippets instead of a full tutorial, jump to JSON Schema examples.

Core keywords

type

Specifies the expected JSON type. Valid values: string, number, integer, boolean, array, object, null.

{ "type": "string" }    // validates: "hello"
{ "type": "integer" }   // validates: 42, not 3.14
{ "type": "number" }    // validates: 42, 3.14
{ "type": ["string", "null"] }  // validates: "hello" or null

properties and required

properties defines a schema for each key. required lists keys that must be present. A key in properties but not in requiredis optional.

{
  "type": "object",
  "required": ["title", "price"],
  "properties": {
    "title": { "type": "string" },
    "price": { "type": "number", "minimum": 0 },
    "description": { "type": "string" }   // optional
  }
}

String constraints

{
  "type": "string",
  "minLength": 1,        // at least 1 character
  "maxLength": 100,      // at most 100 characters
  "pattern": "^[a-z]+$" // must match regex (lowercase letters only)
}

Number constraints

{
  "type": "number",
  "minimum": 0,          // >= 0
  "maximum": 100,        // <= 100
  "exclusiveMinimum": 0, // > 0 (draft-07 style)
  "multipleOf": 0.5      // must be a multiple of 0.5
}

enum

Restricts a value to a fixed set of allowed values.

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

// Also works for mixed types:
{ "enum": [1, "one", null, true] }

format

Provides semantic validation hints. Validators may or may not enforce format checks — it depends on the implementation.

{ "type": "string", "format": "email" }
{ "type": "string", "format": "date" }        // "2024-01-15"
{ "type": "string", "format": "date-time" }   // "2024-01-15T10:30:00Z"
{ "type": "string", "format": "uri" }
{ "type": "string", "format": "uuid" }

Array validation

{
  "type": "array",
  "items": { "type": "string" },   // all items must be strings
  "minItems": 1,                   // at least one item
  "maxItems": 10,                  // at most ten items
  "uniqueItems": true              // no duplicate values
}

Composition keywords

allOf, anyOf, oneOf

// allOf — must satisfy ALL sub-schemas
{
  "allOf": [
    { "type": "object" },
    { "required": ["name"] }
  ]
}

// anyOf — must satisfy AT LEAST ONE sub-schema
{
  "anyOf": [
    { "type": "string" },
    { "type": "number" }
  ]
}

// oneOf — must satisfy EXACTLY ONE sub-schema
{
  "oneOf": [
    { "type": "string", "maxLength": 5 },
    { "type": "string", "minLength": 10 }
  ]
}

not

// Must NOT be a string
{ "not": { "type": "string" } }

$ref and $defs

Use $defs to define reusable sub-schemas and reference them with $ref:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "billing": { "$ref": "#/$defs/address" },
    "shipping": { "$ref": "#/$defs/address" }
  },
  "$defs": {
    "address": {
      "type": "object",
      "required": ["street", "city"],
      "properties": {
        "street": { "type": "string" },
        "city": { "type": "string" },
        "zip": { "type": "string" }
      }
    }
  }
}

Complete annotated example

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Product",
  "type": "object",
  "required": ["id", "name", "price", "category"],
  "additionalProperties": false,
  "properties": {
    "id": {
      "type": "integer",
      "minimum": 1
    },
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200
    },
    "price": {
      "type": "number",
      "minimum": 0,
      "exclusiveMinimum": 0
    },
    "category": {
      "type": "string",
      "enum": ["electronics", "books", "clothing", "food"]
    },
    "tags": {
      "type": "array",
      "items": { "type": "string", "minLength": 1 },
      "uniqueItems": true
    },
    "createdAt": {
      "type": "string",
      "format": "date-time"
    },
    "metadata": {
      "type": "object",
      "additionalProperties": { "type": "string" }
    }
  }
}

Draft versions

JSON Schema has multiple published drafts: draft-04, draft-06, draft-07, draft 2019-09, draft 2020-12. The most widely supported in libraries and tooling is draft-07. When writing schemas, always declare the version with $schema so validators know which spec to use.

Validate JSON against a schema

Paste your JSON and schema into Jsonic's JSON Schema Validator to check for errors instantly. Runs in your browser — nothing is uploaded.

Open JSON Schema Validator

Frequently asked questions

What is JSON Schema?

JSON Schema is a vocabulary for annotating and validating JSON data. A schema is itself a JSON document that describes what valid data looks like — which fields are required, what types values must be, and what constraints they must satisfy. It's widely used for API contract testing, configuration validation, and generating TypeScript types.

What JSON Schema keywords are most commonly used?

The most common keywords are: type, properties, required, enum, minimum/maximum, minLength/maxLength, pattern, format, items, and $ref. Most schemas combine several of these to fully describe the expected data shape.

What is the difference between JSON Schema and JSON?

JSON is a data format for representing structured data. JSON Schema is a way to describe and validate JSON data. A schema document is itself valid JSON, but uses special keywords like type and required to describe rules rather than data. A validator library is needed to check data against a schema.

How do I validate an object with required fields?

Use the required keyword alongside properties. The required array lists property names that must be present. Properties listed in properties but not in required are optional.

What JSON Schema versions exist and which is current?

Published drafts include draft-04, draft-06, draft-07, draft 2019-09, and draft 2020-12. Draft 2020-12 is the current standard, but draft-07 is the most widely supported in validator libraries. Always declare the version with $schema.

How do I add a description to a JSON Schema property?

Use the description keyword inside any schema. It has no effect on validation — it's purely for documentation. Code generators, API explorers, and documentation tools display it to help developers understand each field.

Further reading and primary sources