JSON Schema Validation: How to Define and Validate Your JSON Structure
JSON is flexible. Too flexible, sometimes.
When your API expects a user object with name (string), age (number), and email (valid email format), how do you enforce that? How do you automatically reject invalid data before it corrupts your database?
Enter JSON Schema — a vocabulary for annotating and validating JSON documents.
What Is JSON Schema?
JSON Schema is itself a JSON document that describes the structure of other JSON documents. It defines:
- What fields should exist
- What data types are expected
- What constraints apply (min, max, patterns)
- Which fields are required
Think of it as a contract for your JSON data.
A Simple Example
JSON Data:
{
"name": "Alice",
"age": 30,
"email": "[email protected]"
}
JSON Schema:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"name": { "type": "string" },
"age": { "type": "integer", "minimum": 0 },
"email": { "type": "string", "format": "email" }
},
"required": ["name", "email"]
}
This schema says:
- The root is an object
nameis a string (required)ageis a non-negative integer (optional)emailis a valid email string (required)
Basic Schema Structure
The $schema Keyword
Declares which draft version of JSON Schema you're using:
{
"$schema": "https://json-schema.org/draft/2020-12/schema"
}
Current stable: Draft 2020-12. Draft-07 is still widely used.
The type Keyword
Specifies the expected data type:
{"type": "string"}
{"type": "number"}
{"type": "integer"}
{"type": "boolean"}
{"type": "null"}
{"type": "array"}
{"type": "object"}
Multiple types allowed:
{"type": ["string", "null"]}
The properties Keyword
Defines the schema for object properties:
{
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"}
}
}
The required Keyword
Lists properties that must be present:
{
"type": "object",
"properties": {
"id": {"type": "integer"},
"name": {"type": "string"}
},
"required": ["id"]
}
Data Type Validations
String Validations
{
"type": "string",
"minLength": 1,
"maxLength": 100,
"pattern": "^[A-Za-z]+$"
}
| Keyword | Description |
|---|---|
minLength |
Minimum string length |
maxLength |
Maximum string length |
pattern |
Regex pattern to match |
format |
Semantic format (email, uri, date, etc.) |
Common Formats
{"format": "email"} // Email address
{"format": "uri"} // URI
{"format": "date"} // ISO 8601 date (YYYY-MM-DD)
{"format": "date-time"} // ISO 8601 datetime
{"format": "uuid"} // UUID
{"format": "ipv4"} // IPv4 address
{"format": "ipv6"} // IPv6 address
Number Validations
{
"type": "number",
"minimum": 0,
"maximum": 100,
"multipleOf": 0.5
}
| Keyword | Description |
|---|---|
minimum |
Minimum value (inclusive) |
maximum |
Maximum value (inclusive) |
exclusiveMinimum |
Minimum (exclusive) |
exclusiveMaximum |
Maximum (exclusive) |
multipleOf |
Value must be multiple of this |
Integer vs Number
"type": "number"— allows decimals (42.5)"type": "integer"— whole numbers only (42)
Array Validations
{
"type": "array",
"items": {"type": "string"},
"minItems": 1,
"maxItems": 10,
"uniqueItems": true
}
| Keyword | Description |
|---|---|
items |
Schema for array elements |
minItems |
Minimum array length |
maxItems |
Maximum array length |
uniqueItems |
All items must be unique |
contains |
At least one item matches schema |
Tuple Validation
For arrays with positional types:
{
"type": "array",
"prefixItems": [
{"type": "number"},
{"type": "string"},
{"type": "boolean"}
]
}
Validates: [1, "hello", true]
Object Validations
{
"type": "object",
"minProperties": 1,
"maxProperties": 10,
"additionalProperties": false
}
| Keyword | Description |
|---|---|
minProperties |
Minimum number of properties |
maxProperties |
Maximum number of properties |
additionalProperties |
Allow/disallow extra properties |
propertyNames |
Schema for property names |
Disallowing Extra Properties
{
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"}
},
"additionalProperties": false
}
This rejects {"name": "Alice", "age": 30, "extra": true}.
Advanced Validations
Enum: Fixed Values
{
"type": "string",
"enum": ["pending", "approved", "rejected"]
}
Const: Single Value
{
"type": "string",
"const": "active"
}
Combining Schemas
allOf: Must Match All
{
"allOf": [
{"type": "string"},
{"minLength": 5}
]
}
anyOf: Must Match At Least One
{
"anyOf": [
{"type": "string"},
{"type": "number"}
]
}
oneOf: Must Match Exactly One
{
"oneOf": [
{"type": "integer"},
{"type": "string", "pattern": "^[0-9]+$"}
]
}
not: Must Not Match
{
"not": {"type": "null"}
}
Conditional Schemas
{
"type": "object",
"properties": {
"type": {"enum": ["personal", "business"]},
"company": {"type": "string"}
},
"if": {
"properties": {"type": {"const": "business"}}
},
"then": {
"required": ["company"]
}
}
If type is "business", then company is required.
Nested Object and Array Schemas
Nested Objects
{
"type": "object",
"properties": {
"user": {
"type": "object",
"properties": {
"name": {"type": "string"},
"address": {
"type": "object",
"properties": {
"city": {"type": "string"},
"zip": {"type": "string", "pattern": "^[0-9]{5}$"}
},
"required": ["city"]
}
},
"required": ["name"]
}
}
}
Arrays of Objects
{
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {"type": "integer"},
"name": {"type": "string"}
},
"required": ["id"]
}
}
Reusable Definitions
For complex schemas, use $defs and $ref:
{
"$defs": {
"address": {
"type": "object",
"properties": {
"street": {"type": "string"},
"city": {"type": "string"},
"zip": {"type": "string"}
},
"required": ["city"]
}
},
"type": "object",
"properties": {
"billing": {"$ref": "#/$defs/address"},
"shipping": {"$ref": "#/$defs/address"}
}
}
Using Our JSON Schema Validator
Our JSON Schema validator lets you:
- Paste your JSON in the left panel
- Paste or write your schema in the right panel
- Click Validate to check compliance
- See detailed errors with paths to invalid data
Example Validation
JSON:
{
"name": "Alice",
"age": "thirty"
}
Schema:
{
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"}
}
}
Result:
Validation failed at /age:
Expected: integer
Got: string ("thirty")
JSON Schema in API Documentation
OpenAPI/Swagger
OpenAPI specifications use JSON Schema to define request/response bodies:
paths:
/users:
post:
requestBody:
content:
application/json:
schema:
type: object
properties:
name:
type: string
email:
type: string
format: email
required:
- name
- email
Benefits for API Development
- Auto-generate documentation from schemas
- Validate requests before processing
- Generate client code from schemas
- Test with mock data that conforms to schemas
Practical Tips
Start Simple
Don't try to schema everything at once. Start with type validation and required fields. Add constraints incrementally.
Validate Early
Run validation as close to data entry as possible. Client-side, API gateway, before database writes.
Version Your Schemas
Schemas evolve. Use $id with version numbers:
{
"$id": "https://example.com/schemas/user/v2",
"$schema": "https://json-schema.org/draft/2020-12/schema"
}
Test Your Schemas
Validate that valid data passes AND invalid data fails. Test edge cases.
FAQ: JSON Schema Questions
Is JSON Schema officially standardized?
JSON Schema is an IETF draft standard. While not an official RFC, it's widely adopted. Draft 2020-12 is the current version, with Draft-07 still commonly used in older tools.
How do I validate JSON against a schema programmatically?
Most languages have JSON Schema libraries: ajv (JavaScript), jsonschema (Python), everit-org/json-schema (Java). Parse your schema, compile it, then validate JSON data against it.
Can JSON Schema validate file uploads or binary data?
JSON Schema validates JSON data, not files. For binary, first convert to Base64 string and validate the string format. File validation is typically handled at the application layer.
What's the difference between Draft-07 and Draft 2020-12?
Draft 2020-12 introduced prefixItems (replacing array-form items), $defs (replacing definitions), and improved vocabulary support. Many tools support both, but check compatibility.
Should I use JSON Schema or TypeScript interfaces?
Both serve different purposes. TypeScript interfaces validate at compile time in TypeScript code. JSON Schema validates runtime data from any source (APIs, files, databases). For APIs, use both — TypeScript for code, JSON Schema for runtime validation.
Validate against schema: JSON Schema Validator →
Format your JSON: JSON Formatter →
New to JSON? Start with our guide: What is JSON?