migrating-json-schemas
Migrating JSON Schemas Between Drafts
z-schema supports draft-04, draft-06, draft-07, draft-2019-09, and draft-2020-12. This skill covers migrating schemas between drafts and verifying them with z-schema.
Migration workflow
- Identify the source draft (check
$schemaorid/$idusage). - Set the target version on the validator:
import ZSchema from 'z-schema'; const validator = ZSchema.create({ version: 'draft2020-12' }); - Run
validator.validateSchema(schema)to surface incompatibilities. - Fix each reported error using the keyword mapping below.
- Re-validate until the schema passes.
Quick reference: keyword changes
| Old keyword (draft-04) | New keyword (draft-2020-12) | Introduced in |
|---|---|---|
id |
$id |
draft-06 |
definitions |
$defs |
draft-2019-09 |
Array-form items (tuple) |
prefixItems |
draft-2020-12 |
additionalItems |
items (when prefixItems present) |
draft-2020-12 |
exclusiveMinimum: true (boolean) |
exclusiveMinimum: <number> |
draft-06 |
exclusiveMaximum: true (boolean) |
exclusiveMaximum: <number> |
draft-06 |
dependencies (string arrays) |
dependentRequired |
draft-2019-09 |
dependencies (schema values) |
dependentSchemas |
draft-2019-09 |
$recursiveRef / $recursiveAnchor |
$dynamicRef / $dynamicAnchor |
draft-2020-12 |
For the complete keyword mapping with examples, see references/keyword-mapping.md.
Common migration paths
Draft-04 → Draft-2020-12
This is the largest jump. Apply changes in order:
1. Rename id to $id
// Before (draft-04)
{ "id": "http://example.com/person.json", "type": "object" }
// After (draft-2020-12)
{ "$id": "http://example.com/person.json", "type": "object" }
2. Convert boolean exclusiveMinimum/exclusiveMaximum to numeric
// Before (draft-04)
{ "type": "number", "minimum": 0, "exclusiveMinimum": true }
// After (draft-2020-12)
{ "type": "number", "exclusiveMinimum": 0 }
Note: the minimum keyword is removed when converting to exclusiveMinimum as a number, since exclusiveMinimum: 0 means "greater than 0".
3. Rename definitions to $defs
// Before
{ "definitions": { "address": { "type": "object" } } }
// After
{ "$defs": { "address": { "type": "object" } } }
Update all $ref values that point to #/definitions/... → #/$defs/....
4. Split dependencies
// Before (draft-04) — mixed dependencies
{
"dependencies": {
"billing_address": ["credit_card"],
"credit_card": { "type": "object", "properties": { "cvv": { "type": "string" } } }
}
}
// After (draft-2020-12) — split into two keywords
{
"dependentRequired": {
"billing_address": ["credit_card"]
},
"dependentSchemas": {
"credit_card": { "type": "object", "properties": { "cvv": { "type": "string" } } }
}
}
5. Convert tuple items to prefixItems
// Before (draft-04)
{
"type": "array",
"items": [{ "type": "string" }, { "type": "number" }],
"additionalItems": false
}
// After (draft-2020-12)
{
"type": "array",
"prefixItems": [{ "type": "string" }, { "type": "number" }],
"items": false
}
When items was an array (tuple validation), it becomes prefixItems. The old additionalItems becomes items.
6. Add $schema declaration
{ "$schema": "https://json-schema.org/draft/2020-12/schema" }
Draft-07 → Draft-2020-12
Smaller jump. Main changes:
definitions→$defs(and update$refpaths)- Array-form
items→prefixItems additionalItems→items(whenprefixItemspresent)dependencies→dependentRequired/dependentSchemas- Consider adopting
unevaluatedProperties/unevaluatedItemsfor stricter validation of combined schemas
Draft-2019-09 → Draft-2020-12
Minimal changes:
- Array-form
items→prefixItems,additionalItems→items $recursiveRef/$recursiveAnchor→$dynamicRef/$dynamicAnchor
Verifying a migrated schema
After migration, validate the schema itself against the target draft's meta-schema:
import ZSchema from 'z-schema';
const validator = ZSchema.create({ version: 'draft2020-12' });
try {
validator.validateSchema(migratedSchema);
console.log('Schema is valid for draft-2020-12');
} catch (err) {
console.log('Schema issues:', err.details);
}
Then test data validation to confirm behavior is unchanged:
// Test with known-good data
validator.validate(knownGoodData, migratedSchema);
// Test with known-bad data
const { valid } = validator.validateSafe(knownBadData, migratedSchema);
if (valid) {
console.warn('Migration issue: previously invalid data now passes');
}
Backward compatibility
If schemas must work across multiple draft versions, use version: 'none' and set $schema in each schema to declare its own draft:
const validator = ZSchema.create({ version: 'none' });
Reference files
- references/keyword-mapping.md — Complete keyword mapping across all drafts with before/after examples
More from zaggino/z-schema
writing-json-schemas
Authors JSON Schema definitions for use with z-schema validation. Use when the user needs to write a JSON Schema, define a schema for an API payload, create schemas for form validation, structure schemas with $ref and $defs, choose between oneOf/anyOf/if-then-else, design object schemas with required and additionalProperties, validate arrays with items or prefixItems, add format constraints, organize schemas for reuse, or write draft-2020-12 schemas.
87validating-json-data
Validates JSON data against JSON Schema using the z-schema library. Use when the user needs to validate JSON, check data against a schema, handle validation errors, use custom format validators, work with JSON Schema drafts 04 through 2020-12, set up z-schema in a project, compile schemas with cross-references, resolve remote $ref, configure validation options, or inspect error details. Covers sync/async modes, safe error handling, schema pre-compilation, remote references, TypeScript types, and browser/UMD usage.
74skill-creator
Create, improve, and test skills for the z-schema JSON Schema validator library. Use this skill whenever the user wants to create a new skill from scratch, turn a workflow into a reusable skill, update or refine an existing skill, write test cases for a skill, or organize reference material for a skill. Also use when someone mentions "skill", "SKILL.md", or wants to document a z-schema workflow for reuse by humans or AI agents.
65custom-format-validators
Registers and manages custom format validators in z-schema. Use when the user needs to add custom format validation, create sync or async format validators, register formats globally or per instance, validate emails or dates or phone numbers or custom business rules with format, configure formatAssertions for vocabulary-aware behavior, use customFormats option, list registered formats, handle async format timeouts, or understand how format validation differs across JSON Schema drafts.
64contributing-to-z-schema
Guides contributors through the z-schema codebase, PR workflow, and common development tasks. Use when the user wants to contribute to z-schema, add a new feature or keyword, add an error code, add a format validator, modify options, write tests, run the test suite, fix a failing test, understand the validation pipeline, navigate the source code architecture, or submit a pull request. Also use when someone mentions contributing, PRs, the z-schema source code, or the JSON Schema Test Suite integration.
64handling-validation-errors
Inspects, filters, and maps z-schema validation errors for application use. Use when the user needs to handle validation errors, walk nested inner errors from anyOf/oneOf/not combinators, map error codes to user-friendly messages, filter errors with includeErrors or excludeErrors, build form-field error mappers, use reportPathAsArray, interpret SchemaErrorDetail fields like code/path/keyword/inner, or debug why validation failed.
63