What is JSON Schema?
JSON Schema is a vocabulary for annotating and validating JSON data. It lets you define the exact structure of a JSON document — required fields, their types, allowed values, string formats, and numeric ranges. When you validate JSON against a schema, you know precisely whether the data conforms to the contract.
JSON Schema is used for: - Validating API request and response bodies - Generating documentation from schema definitions - Code generation (TypeScript types, Java classes, Go structs) - Form validation in web and mobile apps - Configuration file validation
Generate a Schema Automatically
Writing JSON Schema by hand is tedious. JSONKit's JSON Schema Generator reads any JSON example and produces a draft-07 compatible schema automatically. Visit /json-schema-generator, paste your JSON, and copy the generated schema.
Given this JSON:
{
"id": 1,
"name": "Ravi Mehta",
"email": "ravi@example.com",
"active": true,
"score": 9.5,
"tags": ["developer", "mentor"]
}The generator produces:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["id", "name", "email", "active", "score", "tags"],
"properties": {
"id": { "type": "integer" },
"name": { "type": "string" },
"email": { "type": "string" },
"active": { "type": "boolean" },
"score": { "type": "number" },
"tags": {
"type": "array",
"items": { "type": "string" }
}
}
}After Generating — What to Customize
The auto-generated schema is a starting point. You should review and add:
String formats:
"email": { "type": "string", "format": "email" }Numeric constraints:
"score": { "type": "number", "minimum": 0, "maximum": 100 }String length limits:
"name": { "type": "string", "minLength": 1, "maxLength": 100 }Optional fields — remove from required if the field can be absent.
Allow null:
"bio": { "type": ["string", "null"] }Validate JSON Against a Schema
Once you have a schema, use JSONKit's JSON Schema Validator (/json-schema-validator) to check data against it. The validator shows field-level errors with the exact JSON path and the violated keyword.
Validate in Node.js:
import Ajv from 'ajv';
import addFormats from 'ajv-formats';
const ajv = new Ajv();
addFormats(ajv);
const validate = ajv.compile(schema);
const valid = validate(data);
if (!valid) console.log(validate.errors);Validate in Python:
import jsonschema
jsonschema.validate(instance=data, schema=schema)
# Raises jsonschema.ValidationError if invalidValidate in Go:
// go get github.com/xeipuuv/gojsonschema
schema, _ := gojsonschema.NewSchema(gojsonschema.NewStringLoader(schemaJson))
result, _ := schema.Validate(gojsonschema.NewStringLoader(dataJson))
if !result.Valid() {
for _, desc := range result.Errors() {
fmt.Println(desc)
}
}Customizing Generated Schemas
The auto-generated schema infers basic types from your JSON sample. Review and tighten these common additions:
Add string format validation:
"email": { "type": "string", "format": "email" },
"createdAt": { "type": "string", "format": "date-time" },
"website": { "type": "string", "format": "uri" },
"id": { "type": "string", "format": "uuid" }Add numeric constraints:
"age": { "type": "integer", "minimum": 0, "maximum": 150 },
"score": { "type": "number", "minimum": 0, "maximum": 100 },
"page": { "type": "integer", "minimum": 1 }Add string length limits:
"name": { "type": "string", "minLength": 1, "maxLength": 100 },
"bio": { "type": "string", "maxLength": 2000 },
"zipCode": { "type": "string", "pattern": "^[0-9]{5,6}$" }Allow null for optional fields:
"bio": { "type": ["string", "null"] },
"middleName":{ "type": ["string", "null"], "maxLength": 50 }Make fields optional — remove them from the required array.
Reusable Definitions with $defs
For schemas with repeated sub-objects, use $defs to define once and reference everywhere:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$defs": {
"Address": {
"type": "object",
"required": ["street", "city", "country"],
"properties": {
"street": { "type": "string" },
"city": { "type": "string" },
"country": { "type": "string", "minLength": 2, "maxLength": 2 }
}
}
},
"type": "object",
"required": ["id", "name", "billingAddress"],
"properties": {
"id": { "type": "string", "format": "uuid" },
"name": { "type": "string" },
"billingAddress": { "$ref": "#/$defs/Address" },
"shippingAddress":{ "$ref": "#/$defs/Address" }
}
}Union Types with anyOf / oneOf
Use anyOf when a field can match multiple schemas (any one must match):
"contact": {
"anyOf": [
{ "type": "string", "format": "email" },
{ "type": "string", "pattern": "^\\+[0-9]{7,15}$" }
]
}Use oneOf for mutually exclusive variants (exactly one must match):
"payment": {
"oneOf": [
{ "$ref": "#/$defs/CardPayment" },
{ "$ref": "#/$defs/UPIPayment" },
{ "$ref": "#/$defs/NetBanking" }
]
}Array Validation
Control array length and content type:
"tags": {
"type": "array",
"items": { "type": "string", "minLength": 1 },
"minItems": 1,
"maxItems": 10,
"uniqueItems": true
}Validate JSON Against Your Schema
Once you have a schema, use JSONKit's JSON Schema Validator to test data against it. The validator shows field-level error paths and the violated keyword.
Node.js (Ajv):
import Ajv from "ajv";
import addFormats from "ajv-formats";
const ajv = new Ajv({ allErrors: true });
addFormats(ajv);
const validate = ajv.compile(schema);
const valid = validate(data);
if (!valid) {
validate.errors?.forEach(err =>
console.error(`${err.instancePath} ${err.message}`)
);
}Python (jsonschema):
import jsonschema
try:
jsonschema.validate(instance=data, schema=schema)
print("Valid")
except jsonschema.ValidationError as e:
print(f"Invalid at {e.json_path}: {e.message}")Go (gojsonschema):
import "github.com/xeipuuv/gojsonschema"
schema, _ := gojsonschema.NewSchema(gojsonschema.NewStringLoader(schemaJSON))
result, _ := schema.Validate(gojsonschema.NewStringLoader(dataJSON))
if !result.Valid() {
for _, err := range result.Errors() {
fmt.Println(err)
}
}CI/CD — Validate JSON on Every Push
Add schema validation to your GitHub Actions pipeline:
- name: Validate API fixtures
run: |
npm install -g ajv-cli ajv-formats
ajv validate -s schemas/user.schema.json -d fixtures/user.json \
--spec=draft2020 --allowUnionTypesJSON Schema vs TypeScript vs Zod
| | JSON Schema | TypeScript | Zod | |---|---|---|---| | Runtime validation | Yes (with library) | No (compile-time only) | Yes | | Multi-language | Yes | No | No | | Code generation | Yes (ts-json-schema-generator) | Via JSON to TS tool | Via zod-to-ts | | Learning curve | Medium | Low | Low | | Best for | Cross-language APIs, docs | TypeScript interfaces | TypeScript runtime validation |
Use JSON Schema for API contracts between services in different languages. Use Zod for TypeScript-first runtime validation. Generate a Zod schema or TypeScript interfaces from your JSON in one click.