JSON Schema basics: a standard for validating data shape
JSON Schema is the standard for defining and validating the shape of JSON data. It powers OpenAPI specs, editor autocomplete for config files, and a lot of API request validation. This article walks through the core keywords and the pitfalls.
What it is
JSON Schema is a spec (IETF Draft) for describing JSON data using JSON.
{
"type": "object",
"properties": {
"name": { "type": "string" },
"age": { "type": "integer", "minimum": 0 }
},
"required": ["name"]
} Against this schema, { "name": "Alice", "age": 30 } is valid; { "age": -5 } is invalid (missing name, negative age).
Core keywords
type
{ "type": "string" }
{ "type": "integer" }
{ "type": "number" }
{ "type": "boolean" }
{ "type": "array" }
{ "type": "object" }
{ "type": "null" } Multiple types:
{ "type": ["string", "null"] } Object properties
{
"type": "object",
"properties": {
"id": { "type": "integer" },
"name": { "type": "string" }
},
"required": ["id", "name"],
"additionalProperties": false
} Without additionalProperties: false, unknown keys pass through silently. Forgetting it is a common bug source.
Arrays
{
"type": "array",
"items": { "type": "integer" },
"minItems": 1,
"maxItems": 100
} String constraints
{
"type": "string",
"minLength": 3,
"maxLength": 50,
"pattern": "^[A-Z][a-z]+$",
"format": "email"
} format recognizes email, uri, date-time, uuid, and so on. Validators differ on how strictly they enforce these.
Number constraints
{
"type": "integer",
"minimum": 0,
"maximum": 100,
"exclusiveMinimum": 0
} Beyond the basics
enum
{ "enum": ["red", "green", "blue"] } Works for any value type, not just strings.
oneOf / anyOf / allOf
{
"oneOf": [{ "type": "string" }, { "type": "integer" }]
} oneOf— matches exactly oneanyOf— matches at least oneallOf— matches all
$ref for reuse
{
"$defs": {
"address": {
"type": "object",
"properties": {
"street": { "type": "string" },
"city": { "type": "string" }
}
}
},
"type": "object",
"properties": {
"shipping": { "$ref": "#/$defs/address" },
"billing": { "$ref": "#/$defs/address" }
}
} Reuse common shapes via $ref. OpenAPI puts these under components.schemas and references them across paths.
Where it shows up
1. API specs (OpenAPI / Swagger)
OpenAPI uses JSON Schema for request/response shapes, enabling docs, mock servers, and client generation.
2. Config files
VS Code, ESLint, Prettier publish JSON Schemas; editors use them for autocomplete and inline validation.
3. Form / request validation
On the server, libraries like Ajv accept a JSON Schema and validate incoming bodies against it.
4. Database constraints
Postgres JSONB columns can enforce a JSON Schema via a CHECK constraint.
Common traps
1. Forgetting additionalProperties
{
"properties": {
"name": { "type": "string" }
}
} This says “if name exists it must be a string”. Unknown keys pass without complaint. Set additionalProperties: false for strict shapes.
2. integer vs number
number accepts floats; integer accepts whole numbers. Validators disagree on how to handle 1.0 against integer.
3. format enforcement varies
format: "email" regex differs across validators. For real email validation, use a dedicated library.
4. Nullable representations differ
OpenAPI 3.0 uses nullable: true; pure JSON Schema uses type: ["string", "null"]. Don’t mix them.
Summary
- JSON Schema describes JSON shape in JSON.
- Core keywords:
type,properties,required,additionalProperties. $reffor reuse;oneOf,anyOf,allOffor combinations.- Used in API specs, config files, form validation.
When designing a new API, drafting the JSON Schema before the code reduces rework. The JSON validator on this site takes both schema and candidate data and surfaces errors inline, which is enough for schema-design iteration. For CI integration or full OpenAPI validation, reach for ajv or spectral — the in-browser validator is for the exploratory phase, not the production pipeline.