Skip to content
Back to skills

Migrating Json Schemas

ASecurity

Migrates JSON Schemas between draft versions for use with z-schema. Use when the user wants to upgrade schemas from draft-04 to draft-2020-12, convert between draft formats, update deprecated keywords, replace id with $id, convert definitions to $defs, migrate items to prefixItems, replace dependencies with dependentRequired or dependentSchemas, adopt unevaluatedProperties or unevaluatedItems, or adapt schemas to newer JSON Schema features.

  • 57 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 17, 2026
toolstypescriptgo

Security analysis

A100/100

Scanned October 17, 2026

npx -y skills add diegosouzapw/awesome-omni-skill --skill migrating-json-schemas --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Migrating Json Schemas?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Migrating Json Schemas
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/diegosouzapw-migrating-json-schemas/badge)](https://www.skillsdirectory.com/skills/diegosouzapw-migrating-json-schemas)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: migrating-json-schemas
description: Migrates JSON Schemas between draft versions for use with z-schema. Use when the user wants to upgrade schemas from draft-04 to draft-2020-12, convert between draft formats, update deprecated keywords, replace id with $id, convert definitions to $defs, migrate items to prefixItems, replace dependencies with dependentRequired or dependentSchemas, adopt unevaluatedProperties or unevaluatedItems, or adapt schemas to newer JSON Schema features.
---

# 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

1. Identify the source draft (check `$schema` or `id`/`$id` usage).
2. Set the target version on the validator:
   ```typescript
   import ZSchema from 'z-schema';
   const validator = ZSchema.create({ version: 'draft2020-12' });
   ```
3. Run `validator.validateSchema(schema)` to surface incompatibilities.
4. Fix each reported error using the keyword mapping below.
5. 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](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`**

```json
// 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**

```json
// 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`**

```json
// Before
{ "definitions": { "address": { "type": "object" } } }

// After
{ "$defs": { "address": { "type": "object" } } }
```

Update all `$ref` values that point to `#/definitions/...` → `#/$defs/...`.

**4. Split `dependencies`**

```json
// 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`**

```json
// 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**

```json
{ "$schema": "https://json-schema.org/draft/2020-12/schema" }
```

### Draft-07 → Draft-2020-12

Smaller jump. Main changes:

1. `definitions` → `$defs` (and update `$ref` paths)
2. Array-form `items` → `prefixItems`
3. `additionalItems` → `items` (when `prefixItems` present)
4. `dependencies` → `dependentRequired` / `dependentSchemas`
5. Consider adopting `unevaluatedProperties` / `unevaluatedItems` for stricter validation of combined schemas

### Draft-2019-09 → Draft-2020-12

Minimal changes:

1. Array-form `items` → `prefixItems`, `additionalItems` → `items`
2. `$recursiveRef`/`$recursiveAnchor` → `$dynamicRef`/`$dynamicAnchor`

## Verifying a migrated schema

After migration, validate the schema itself against the target draft's meta-schema:

```typescript
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:

```typescript
// 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:

```typescript
const validator = ZSchema.create({ version: 'none' });
```

## Reference files

- [references/keyword-mapping.md](references/keyword-mapping.md) — Complete keyword mapping across all drafts with before/after examples

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.