Draft 2019-09 to Draft 2020-12

Introduction

JSON Schema Draft 2020-12 introduces key improvements over Draft 2019-09, focusing on improved modularity and cross-referencing capabilities. This means improvements for schema resuse, being able to define features a schema supports, etc. This guide covers all major changes and how to migrate from Draft 2019-09 to Draft 2020-12.

Keyword changelog

Keyword (Draft 2019-09) Keyword (Draft 2020-12) Specification Keyword Type Behavior Details
$anchor remained $anchor Core In 2019-09, $anchor could use a colon and not start with an underscore, but in 2020-12, the upgrade in syntax rule can't use a colon.
$schema remained $schema Core The behavior was updated to use dialect 2020-12
$recursiveAnchor $dynamicAnchor Core Identifier Similar to $anchor, but supports $dynamicRef for flexible schema resolution and $dynamicAnchor now has its own syntax.
$recursiveRef $dynamicRef Core Identifier Works with $dynamicAnchor to allow referencing dynamically resolved schemas at runtime.
$vocabulary $vocabulary Core Identifier Specifies which vocabularies a schema uses in 2019-09, but the update now uses format-annotation aiding compatibility and extensibility.
items (used for both lists and tuples) prefixItems Core Applicator/Annotation Separates tuple validation (prefixItems) from list validation (items). Now, items applies only to additional elements beyond prefixItems.
$vocabulary Core

Tutorial

Migration Steps

1. Updating $schema Declaration

Reference the correct Draft 2020-12 meta-schema to ensure compatibility:

Before (Draft 2019-09):

1{
2  "$schema": "https://json-schema.org/draft/2019-09/schema"
3}
4

After (Draft 2020-12):

1{
2  "$schema": "https://json-schema.org/draft/2020-12/schema"
3}
4
2. Using $dynamicAnchor and $dynamicRef

Switch to $dynamicAnchor when defining flexible anchors:

Before (Draft 2019-09):

1{
2  "$anchor": "mySchema"
3}
4

After (Draft 2020-12):

1{
2  "$dynamicAnchor": "mySchema"
3}
4

Use $dynamicRef instead of $recursiveRef for dynamic references:

Example:

1{
2  "$schema": "https://json-schema.org/draft/2020-12/schema",
3  "$dynamicAnchor": "baseSchema"
4}
5

To reference dynamically:

1{
2  "$dynamicRef": "#baseSchema"
3}
4
3. Declaring Supported Vocabularies with $vocabulary

Explicitly declare the vocabularies your schema uses:

Example:

1{
2  "$schema": "https://json-schema.org/draft/2020-12/schema",
3  "$vocabulary": {
4    "https://json-schema.org/draft/2020-12/vocab/core": true,
5    "https://json-schema.org/draft/2020-12/vocab/applicator": true
6  }
7}
8
4. Replacing items with prefixItems for Tuple Validation

For fixed-length arrays (tuples), replace items with prefixItems:

Before (Draft 2019-09):

1{
2  "type": "array",
3  "items": [
4    { "type": "string" },
5    { "type": "number" }
6  ]
7}
8

After (Draft 2020-12):

1{
2  "type": "array",
3  "prefixItems": [
4    { "type": "string" },
5    { "type": "number" }
6  ]
7}
8

To validate additional items beyond prefixItems, items can still be used:

1{
2  "type": "array",
3  "prefixItems": [
4    { "type": "string" },
5    { "type": "number" }
6  ],
7  "items": { "type": "boolean" }
8}
9

These improvements ensure compliance with the latest JSON Schema standards while improving maintainability and extensibility of your schemas.

Need Help?

Did you find these docs helpful?

Help us make our docs great!

At JSON Schema, we value docs contributions as much as every other type of contribution!

Still Need Help?

Learning JSON Schema is often confusing, but don't worry, we are here to help!.