JSON Schema & Validation
JSON Schema is a vocabulary for describing the structure of JSON documents. Zod and Ajv are the most common validators in JS/TS projects.
JSON Schema basics
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["name", "email"],
"properties": {
"name": { "type": "string", "minLength": 1 },
"email": { "type": "string", "format": "email" },
"age": { "type": "integer", "minimum": 0, "maximum": 150 },
"tags": {
"type": "array",
"items": { "type": "string" },
"uniqueItems": true
}
},
"additionalProperties": false
}Zod (TypeScript-first)
import { z } from 'zod'
const UserSchema = z.object({
name: z.string().min(1),
email: z.string().email(),
age: z.number().int().min(0).max(150).optional(),
tags: z.array(z.string()).default([]),
})
type User = z.infer<typeof UserSchema> // ← derive type from schema
// parse — throws ZodError on failure
const user = UserSchema.parse(rawJson)
// safeParse — returns { success, data } | { success: false, error }
const result = UserSchema.safeParse(rawJson)
if (!result.success) {
console.error(result.error.issues)
}Validating API responses
async function fetchUser(id: string): Promise<User> {
const res = await fetch(`/api/users/${id}`)
if (!res.ok) throw new Error(`HTTP ${res.status}`)
const raw = await res.json() // unknown — don't trust it
return UserSchema.parse(raw) // throws if API shape changed
}
// This pattern catches API contract breaks at runtime,
// not silently at the point of use.Common schema keywords
type — "string" | "number" | "integer" | "boolean" | "null" | "object" | "array"
enum — restrict to a set of values: { "enum": ["red", "green", "blue"] }
const — single allowed value: { "const": "active" }
anyOf / oneOf / allOf — composing schemas
required — array of required keys on an object
additionalProperties: false — reject unknown keys
$ref — reference another schema definition to avoid repetition
Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free