draft-07 или 2020-12
Главное: 2020-12 актуален и добавляет $defs, prefixItems и unevaluatedProperties, но многие инструменты всё ещё понимают только draft-07. Выбирайте по тому, что поддерживает весь ваш инструментарий.

Главное: используйте 2020-12 для новых проектов, откатывайтесь к draft-07 в момент, когда любой валидатор, генератор кода или инструмент OpenAPI поддерживает только его, и всегда закрепляйте драфт через $schema.
Короткий ответ: 2020-12 для новой работы, draft-07 когда этого требует старый компонент.
Хронология
| Драфт | Год | Примечательное |
|---|---|---|
| draft-04 | 2013 | id вместо $id; всё ещё распространён в старых API |
| draft-06 | 2017 | const, propertyNames |
| draft-07 | 2018 | if/then/else, readOnly, contentMediaType; лучшая совместимость |
| 2019-09 | 2019 | $defs заменяет definitions, unevaluatedProperties |
| 2020-12 | 2020 | prefixItems, $dynamicRef; текущая рекомендация |
Что улучшает 2020-12
Кортежи массивов перестают быть особым случаем. draft-07 выражает «первый элемент — A, второй — B» через items: [{...}, {...}] плюс additionalItems. 2020-12 использует prefixItems для схем по позициям и items для остального.
$defs — стандартное имя. Инструменты, написанные после 2019, по умолчанию смотрят туда.
unevaluatedProperties работает с композицией. С allOf additionalProperties: false отвергает поля, определённые соседними ветками. unevaluatedProperties: false учитывает только свойства, фактически вычисленные всей схемой, что и нужно композиции.
Когда draft-07 — правильный ответ
| Ситуация | Причина |
|---|---|
| OpenAPI 3.0 | Его объект схемы — подмножество draft-04/07 |
| Старые валидаторы (ajv 6, некоторые библиотеки Java) | Они не знают prefixItems или $dynamicRef |
| Платформа предписывает версию | Некоторые low-code-платформы и шлюзы закрепляют её |
| Генераторы кода, останавливающиеся на 07 | Неизвестные ключевые слова молча игнорируются |
Проверьте последний случай напрямую: отправьте схему с prefixItems вашему валидатору. Если она проходит без жалоб вместо сообщения о неизвестном ключевом слове, он игнорирует ограничение — самый опасный исход из всех.
Смешивание версий
Всегда объявляйте $schema. Значения по умолчанию различаются: ajv предполагает draft-07, несколько библиотек Python предполагают 2020-12. Тогда один и тот же файл валидируется по-разному в двух местах.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/schemas/order.json",
"type": "object"
}
Не используйте $ref между драфтами. Поведение неопределено.
Обновляйте пакетами. Два драфта в одном репозитории превращают «какие правила здесь применяются» в племенное знание.
Вопросы и ответы
Как проверить, поддерживает ли мой валидатор 2020-12?
Отправьте валидатору схему, использующую prefixItems. Ошибка неизвестного ключевого слова означает, что он не поддерживает драфт; молчаливый проход означает, что он игнорирует ограничение, что хуже.
Почему один проект должен использовать один драфт?
Два драфта в одном репозитории превращают «какие правила здесь применяются» в племенное знание. Обновляйте пакетами, чтобы каждый файл разделял одну интерпретацию.
Всегда ли нужно объявлять $schema?
Да. Значения по умолчанию различаются: ajv предполагает draft-07, а несколько библиотек Python предполагают 2020-12, поэтому один и тот же файл может валидироваться по-разному в двух местах.