JSON Schema keywords (2020-12)
JSON Schema is a vocabulary for validating and annotating JSON documents. The 2020-12 draft organizes its keywords into vocabularies: core, validation, applicators, and annotations. This reference lists the keywords developers reach for most, with the JSON types each applies to and the exact assertion it makes.
How it works
Evaluation walks the schema against an instance. A validation keyword directly asserts a constraint — minimum checks a number, pattern matches a string against a regex, required lists mandatory object members. These produce a pass/fail boolean.
An applicator keyword does not assert anything itself; it applies subschemas to parts of the instance. properties maps names to subschemas, items applies a schema to array elements, and allOf/anyOf/oneOf combine subschemas logically. The instance is valid only if the delegated subschemas validate.
Core keywords structure the document: $id sets the base URI, $ref/$dynamicRef reference other schemas, and $defs holds reusable subschemas. A key 2020-12 change is that $ref may now coexist with sibling keywords rather than replacing them.
Annotation keywords (title, description, default, examples, deprecated, readOnly) attach metadata without affecting validity, and are gathered as annotations for tooling.
Tips and example
A schema mixing several keyword groups:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"age": { "type": "integer", "minimum": 0 },
"tags": { "type": "array", "items": { "type": "string" } }
},
"required": ["age"],
"additionalProperties": false
}
Remember that additionalProperties: false only sees properties not matched by properties or patternProperties — a frequent source of confusion. Filter the table below by group to confirm what any keyword applies to before relying on it.
The most commonly misunderstood keywords
additionalProperties and properties interact subtly. If you declare additionalProperties: false but forget to list a property in properties, that property is treated as “additional” and fails validation — even if the instance includes it. This is one of the most common sources of unexpected validation failures.
items changed meaning between drafts. In draft-07 and earlier, items could be an array to validate elements positionally (tuple validation). In 2020-12, that role moved to prefixItems, and items now only applies to elements after the prefix. If you port a schema from draft-07 to 2020-12, an items: [...] array silently stops working as intended.
$ref behaviour changed in 2020-12. In older drafts, a $ref in a schema object replaced all sibling keywords — they were ignored. In 2020-12, $ref is just another applicator keyword and sibling keywords are applied too. A schema like { "$ref": "#/$defs/Base", "description": "A base object" } is valid in 2020-12 but the description would be ignored in draft-07.
format is not validation by default. The format keyword annotates the instance type (like email, uri, date-time) but does not assert a constraint unless the validator explicitly enables format assertion. Many validators default to treating format as metadata only. If you need guaranteed email or URL validation, pair format with a pattern keyword.
Keyword groups at a glance
| Group | Purpose | Examples |
|---|---|---|
| Validation | Assert constraints on the instance | type, minimum, maxLength, required, pattern, enum |
| Applicator | Apply subschemas to parts of the instance | properties, items, prefixItems, allOf, anyOf, oneOf, if/then/else |
| Core | Structure and reference the schema itself | $id, $ref, $defs, $schema, $anchor |
| Annotation | Attach metadata without validating | title, description, default, examples, deprecated |
Keywords from different groups can coexist freely in one schema object. A common pattern is to combine a validation keyword (type: "string") with annotation keywords (title, description) and an applicator (pattern) in a single property definition.