The Vocabulary System
The most significant architectural change in JSON Schema 2020-12 is the formal vocabulary system. Previous drafts bundled all keywords into a single meta-schema. 2020-12 separates them into distinct vocabularies, each with its own URI:
- Core — structural keywords like
$id,$ref,$defs - Applicator — combining keywords like
if/then/else,anyOf,allOf - Validator — constraint keywords like
type,minimum,maxLength - Annotation — documentation keywords like
title,description,default - Format Annotation / Assertion — the
formatkeyword - Content —
contentEncoding,contentMediaType - Unevaluated —
unevaluatedProperties,unevaluatedItems
A meta-schema declares which vocabularies it uses via the $vocabulary keyword. This allows custom dialects that extend or restrict the standard keyword set, enabling domain-specific schema languages built on the JSON Schema infrastructure.
$dynamicRef and $dynamicAnchor
Prior drafts lacked a clean way to write recursive schemas where a sub-schema in a bundled definition could be overridden by the consuming schema. The $recursiveRef and $recursiveAnchor keywords in 2019-09 were an attempt to solve this but had design problems.
2020-12 replaces them with $dynamicRef and $dynamicAnchor. A schema that uses $dynamicAnchor to mark an extension point can be referenced by a consuming schema that replaces that anchor with its own definition. This enables reusable meta-schemas and extensible vocabulary definitions — key requirements for framework authors building on top of JSON Schema.
Restructured Keywords
Several keywords were renamed or restructured to align with the new vocabulary architecture:
itemsis now used only for single-schema tuple validation; the old positional items behaviour moves toprefixItemsadditionalItemsis replaced byitemsin the new usage (additional items afterprefixItems)$recursiveRef/$recursiveAnchorreplaced by$dynamicRef/$dynamicAnchor
These changes are breaking relative to 2019-09 schemas that used positionalitems as an array of sub-schemas.
Migrating from Earlier Drafts
Migrating from draft-07 or 2019-09 to 2020-12 requires attention to the items / prefixItems change and any use of $recursiveRef. For schemas that don't use these features, the migration is often a declaration change: update $schema to https://json-schema.org/draft/2020-12/schema and run your existing test suite against a 2020-12 validator.
The JSON Schema website maintains a comprehensive reference documenting all keywords across all drafts, which is useful for identifying migration steps specific to your schemas.