JSON Schema has had eight specification drafts. Draft 7 (2018) is the most widely deployed. Draft 2020-12 is the current version and the one most modern tooling targets. Here's what changed, what broke, and which one your project should use.
The short answer
Use Draft 2020-12 for new projects. Use Draft 7 if you're integrating with an existing system that requires it (OpenAPI 3.0 is a notable example — it uses a Draft 4 subset). Both are well-supported by libraries; Draft 2020-12 adds capabilities without breaking most existing schemas.
How JSON Schema versions work
A schema declares its version with the $schema keyword at the root:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
...
}
Validators read this to determine which keyword set to apply. If $schema is missing, most validators default to the latest version they support, which can cause surprises if the schema was written for an older draft.
What 2020-12 added
Real array tuple validation. In Draft 7, the items keyword did double duty: with a single schema, it validated every element; with an array of schemas, it validated each position (a tuple). Draft 2020-12 split these into items (single schema, every element) and prefixItems (array of schemas, positional). This is clearer but breaks schemas that used the old form.
// Draft 7 — positional tuple validation
{
"type": "array",
"items": [{"type": "string"}, {"type": "number"}]
}
// Draft 2020-12 — equivalent
{
"type": "array",
"prefixItems": [{"type": "string"}, {"type": "number"}]
}
Dynamic references. Draft 2020-12 introduced $dynamicRef and $dynamicAnchor, which let a referenced schema be overridden by the schema that references it. This enables real schema inheritance — you can define an abstract "base" schema with placeholders that derived schemas fill in. Draft 7 had no equivalent; you needed code generation or pre-processing to achieve similar results.
Vocabularies. Draft 2020-12 formalized schema vocabularies — named collections of keywords that a validator can support or ignore. This is mostly important for tool authors and schema publishers; for most users it's transparent.
Annotation collection. Annotation keywords like title, description, examples, and default now have well-defined collection semantics. Tools that build UIs or documentation from schemas benefit; pure validators can ignore this.
What 2020-12 removed or changed
Boolean schemas. Already in Draft 6, but worth noting: a schema can now be just true (matches anything) or false (matches nothing). Useful inside additionalProperties and similar.
Behavior of $ref. In Draft 7, $ref was supposed to be the only key in its object — siblings were ignored. In Draft 2020-12, siblings are honored. This is more intuitive but means schemas that relied on siblings being ignored will now apply them. Most schemas don't put siblings next to $ref, so this rarely breaks anything in practice.
"definitions" → "$defs". The keyword for reusable subschemas was renamed from definitions to $defs. Many validators accept both for compatibility, but new schemas should use $defs.
Migration in practice
For a Draft 7 schema you want to upgrade:
- Change
$schemato the 2020-12 URL. - Rename
definitionsto$defs(if used). - Convert positional
itemsarrays toprefixItems. - Check
additionalItemsusage — it's been replaced byitemsafterprefixItems. - Run your test corpus against the upgraded schema to confirm behavior hasn't changed.
Most schemas migrate in five minutes. The exceptions are schemas that lean heavily on positional tuples or had $ref with siblings.
What's between Draft 7 and 2020-12?
Two intermediate drafts exist: 2019-09 and 2020-12 itself. Draft 2019-09 introduced $defs, $anchor, dependentRequired, and dependentSchemas. Draft 2020-12 polished the dynamic-ref design and split items from prefixItems.
If you're stuck on a library that only supports 2019-09, you get most of 2020-12's improvements minus the prefixItems rename. It's a fine intermediate stop.
OpenAPI compatibility
OpenAPI 3.0 uses a Draft 4 subset with some divergences. OpenAPI 3.1 (released 2021) aligned with JSON Schema Draft 2020-12 — they're now fully compatible. If your project is on OpenAPI 3.0, you're stuck with the older subset. If you can move to 3.1, you get full JSON Schema compliance.
Choosing what to ship
For new schemas, default to 2020-12. For documentation, link to the 2020-12 spec. If you're publishing a schema for others to consume — say, a public API contract — consider whether your consumers' tooling supports 2020-12 before committing. Most modern validators do; some older code may need an upgrade.
If you want to validate against either draft from the browser, our JSON Schema Validator supports both. For broader context on schema design, see our guide to understanding JSON Schema.