JSON Schema is a standard for describing and validating the structure of JSON data. You write a schema, a small JSON document that declares what fields a payload should contain, their types, and which ones are required. A validator then checks any JSON against that schema and reports exactly what is wrong. It works like a contract for your data.
That contract solves two problems at once: it catches bad data before it breaks your code, and it doubles as living documentation. If you already work with API specs, JSON Schema sits underneath them, the same way it powers the request and response shapes in an OpenAPI specification example. This guide explains what JSON Schema is, shows worked examples, and covers the keywords and types you will use every day.
What is JSON Schema, exactly?
JSON Schema is itself written in JSON. A schema is a set of rules, expressed as keywords, that describe a valid JSON value. The most common use is validation: confirming that an incoming object has the right fields with the right types. The second use is documentation, since a schema reads as a precise description of a data structure.
A plain JSON file tells you what one example looks like. A JSON Schema tells you what every valid example must look like. That difference is why teams adopt it for API request bodies, configuration files, message queues, and form input.
Why JSON Schema matters
Without validation, bad data slips through and surfaces as a confusing error three functions later. With a schema, you reject the bad payload at the door with a clear message. This matters most at system boundaries: API endpoints, webhooks, and config loading.
The documentation benefit is just as practical. A schema is machine-readable, so tools can render it as a reference table, generate sample payloads, or scaffold client code. Good REST API documentation leans on schemas so that the field list a reader sees matches what the server actually enforces.
A basic JSON Schema example
Here is a small schema for a user object. It says a user is an object with a name string, an age integer, and an email string, and that name and email are required.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "User",
"type": "object",
"properties": {
"name": { "type": "string" },
"age": { "type": "integer" },
"email": { "type": "string", "format": "email" }
},
"required": ["name", "email"]
}
This JSON validates against the schema above:
{
"name": "Ada Lovelace",
"age": 36,
"email": "ada@example.com"
}
This JSON fails, because email is missing and age is a string, not an integer:
{
"name": "Grace Hopper",
"age": "thirty"
}
JSON Schema data types
Every value in a schema is described by a type keyword. JSON Schema defines seven core types, the same primitives JSON itself supports plus the two container types.
| Type | Describes | Example value |
|---|---|---|
string | Text | "hello" |
number | Any numeric value, including decimals | 3.14 |
integer | Whole numbers only | 42 |
object | Key/value collection | { "id": 1 } |
array | Ordered list | [1, 2, 3] |
boolean | True or false | true |
null | The null value | null |
You can allow more than one type by passing an array, for example "type": ["string", "null"] for a field that may be text or empty.
Common JSON Schema keywords
Keywords are the building blocks of a schema. The table below covers the ones you will reach for in almost every schema.
| Keyword | What it does |
|---|---|
$schema | Declares which JSON Schema version (draft) the document uses |
type | Sets the allowed data type for a value |
properties | Defines the named fields of an object and their schemas |
required | Lists which properties must be present |
items | Defines the schema each element of an array must match |
enum | Restricts a value to a fixed set of options |
format | Adds a semantic hint like email, date-time, or uri |
$ref | Reuses another schema by reference instead of repeating it |
minimum / maximum | Sets numeric bounds |
minLength / maxLength | Sets string length bounds |
additionalProperties | Controls whether unlisted fields are allowed |
A few of these deserve a closer look.
type, properties, and required
These three keywords do most of the work. type says what kind of value you expect, properties describes each field of an object, and required marks the fields that cannot be omitted. A field listed in properties is optional unless you also name it in required.
enum and format
Use enum when a value must be one of a known list, such as "status": { "enum": ["active", "paused", "closed"] }. Use format to signal intent for strings: email, date, date-time, uri, and uuid are widely supported. Note that format is a hint, and not every validator enforces it by default.
items
items applies a schema to every element in an array. To require an array of strings you write "type": "array", "items": { "type": "string" }. Add minItems or uniqueItems to constrain length or forbid duplicates.
$schema and $ref
$schema points to the draft you are writing against, which tells validators how to interpret the rest of the document. $ref lets you define a shape once and reuse it. If you have an address object used by both a customer and a supplier, you define it once and reference it with $ref in both places. This keeps large schemas readable and consistent, the same discipline a data dictionary brings to a database.
A fuller worked example
The schema below describes a blog post. It uses nested objects, an array of strings with constraints, an enum, a format, numeric bounds, and $ref for a reusable author object.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "BlogPost",
"type": "object",
"properties": {
"id": { "type": "integer", "minimum": 1 },
"title": { "type": "string", "minLength": 1, "maxLength": 120 },
"status": { "enum": ["draft", "published", "archived"] },
"publishedAt": { "type": "string", "format": "date-time" },
"tags": {
"type": "array",
"items": { "type": "string" },
"uniqueItems": true
},
"author": { "$ref": "#/$defs/author" }
},
"required": ["id", "title", "status"],
"additionalProperties": false,
"$defs": {
"author": {
"type": "object",
"properties": {
"name": { "type": "string" },
"email": { "type": "string", "format": "email" }
},
"required": ["name"]
}
}
}
Setting additionalProperties to false means any field not listed in properties makes the payload invalid. That strictness is useful for catching typos like titel before they reach production.
JSON Schema for API documentation
JSON Schema is the foundation of modern API specs. In OpenAPI, every request body and response is described with a JSON Schema object. So when you document an endpoint, you are really writing schemas. That overlap is why the question of Swagger vs OpenAPI often comes up alongside JSON Schema: Swagger is the older tooling, OpenAPI is the current spec, and both rely on schemas to describe data shapes.
Because a schema is structured data, you can render it into a clean reference page automatically. Tools like Docsio turn your API and schema docs into a branded, searchable site, so the field tables your readers see stay in sync with the rules your server enforces. If you want more patterns to model, our roundup of API documentation examples shows how schemas appear in published docs.
How do you validate JSON against a schema?
Validation is the step where a tool checks a JSON document against your schema and returns pass or fail with error details. You rarely write a validator yourself. Instead you pick a library for your language and feed it the schema plus the data.
Popular validators include Ajv for JavaScript and TypeScript, jsonschema for Python, python-jsonschema bindings, everit-json-schema and networknt for Java, and go-jsonschema style libraries for Go. A typical flow in Node looks like this:
{
"step1": "Load your schema file",
"step2": "Create a validator with the schema",
"step3": "Run validator(data)",
"step4": "Read the errors array if validation fails"
}
The validator returns a list of errors, each pointing at the exact path that failed, such as /author/email. That precise location is what makes schema validation faster to debug than ad hoc field checks.
JSON Schema tools
A few categories of tooling cover most needs:
- Validators: Ajv,
jsonschema(Python), and similar libraries enforce schemas at runtime. - Generators: tools that infer a draft schema from a sample JSON document, giving you a starting point to refine.
- Online playgrounds: web validators let you paste a schema and a payload to test the result instantly.
- Editors: many IDEs offer autocomplete and inline validation when a JSON file references a schema.
- Doc renderers: spec and docs tools render schemas into human-readable reference pages.
Best practices for writing JSON Schema
A few habits keep schemas maintainable as they grow.
- Always set
$schemaso validators know which draft to apply. - Add a
titleanddescriptionto each schema and field. These flow straight into generated docs. - Use
$reffor repeated shapes instead of copying objects. One definition, many references. - Be deliberate about
additionalProperties. Set it tofalsewhen you want to reject unexpected fields, and leave it open when you expect forward-compatible extensions. - Keep
requiredhonest. Mark only the fields your code truly depends on, so optional data does not get rejected. - Validate at the boundary. Check incoming data at API entry points and config load, not deep inside business logic.
Conclusion
JSON Schema gives your JSON data a contract: a precise, machine-readable description that validators enforce and documentation tools render. Start with type, properties, and required, add enum, format, items, and $ref as your data grows, and validate at every boundary. The same schemas that catch bad payloads also become the reference your team and your API consumers read. Write the schema once, and let it both guard and document your data.
Frequently asked questions
What is JSON Schema used for?
JSON Schema is used to validate and document the structure of JSON data. Validators check that a payload has the correct fields, types, and required values, rejecting bad data at system boundaries like API endpoints. It also serves as machine-readable documentation that tools can render into reference pages.
What is the difference between JSON and JSON Schema?
JSON is a data format that holds one specific set of values. JSON Schema is a separate JSON document that describes the rules every valid JSON of that kind must follow. In short, JSON is the data, and JSON Schema is the contract that defines and validates the shape of that data.
Is JSON Schema still used?
Yes. JSON Schema is widely used and actively maintained, with the 2020-12 draft as the current stable version. It underpins API specifications like OpenAPI, configuration validation, and form handling across most programming languages, and major tools ship validators and editor support for it.
How do you validate JSON against a schema?
You use a validation library for your language, such as Ajv for JavaScript or jsonschema for Python. You load the schema, pass it the JSON data, and the validator returns whether the data passes plus a list of errors. Each error points to the exact field path that failed.
What are the core JSON Schema data types?
JSON Schema defines seven types: string, number, integer, object, array, boolean, and null. You assign one with the type keyword, or allow several by passing an array of types. These map directly to the value kinds that JSON itself supports.
