Переход между основными версиями библиотеки Ajv сопровождается изменениями в поведении валидатора, расширением поддержки спецификаций JSON Schema и переработкой внутренних оптимизаций компиляции схем. На практике миграция чаще всего затрагивает переходы между версиями v6 → v7 → v8, где каждая ветка приносит как функциональные улучшения, так и изменения, нарушающие обратную совместимость.
Ключевая сложность миграции заключается в том, что Ajv активно следует изменениям стандартов JSON Schema (Draft 07, 2019-09, 2020-12), а также пересматривает собственные расширения. Поэтому код, корректно работавший в одной версии, может требовать пересмотра опций, подключаемых модулей и структуры схем.
Основное изменение связано с удалением и переработкой поведения по умолчанию.
В v7 были удалены или вынесены в плагины:
jsonPointers как основной механизм работы с
ошибкамиКод, использующий подобные возможности, требует явного подключения дополнительных пакетов или замены логики.
Строгий режим стал более агрессивным:
Это приводит к необходимости предварительной валидации самих схем перед использованием.
Начиная с v7, многие встроенные форматы были вынесены из ядра библиотеки.
Ранее встроенные проверки:
перестали быть частью ядра и требуют подключения пакета
ajv-formats.
Пример изменения архитектуры:
import Ajv from "ajv";
import addFormats from "ajv-formats";
const ajv = new Ajv();
addFormats(ajv);
Без этого шага схемы, использующие стандартные форматы, начинают возвращать ошибки валидации.
Версия v8 ориентирована на поддержку JSON Schema 2020-12 и упрощение внутренней модели компиляции.
В v8 полностью исключены:
Теперь требуется более явная конфигурация валидатора.
В v8 пересмотрена структура инициализации:
import Ajv from "ajv";
const ajv = new Ajv({
strict: true,
allErrors: true
});
allErrors теперь влияет на производительность сильнее,
чем в предыдущих версияхstrict стал фактическим стандартом и рекомендуется
оставлять включённымОдно из наиболее частых источников проблем при миграции — изменение
поведения coerceTypes.
const ajv = new Ajv({ coerceTypes: true });
Типы могли преобразовываться автоматически при валидации.
Поведение стало более предсказуемым:
Это снижает количество скрытых ошибок, но требует пересмотра логики обработки входных данных.
Опция useDefaults также была переработана.
Пример:
const ajv = new Ajv({
useDefaults: true,
strict: true
});
В сложных схемах требуется учитывать, что дефолты могут не применяться рекурсивно без дополнительных настроек.
С переходом между версиями усилилась привязка к спецификации.
const и enumif/then/elseoneOf, anyOf,
allOfОсобенно заметно изменение поведения oneOf, где ранее
допускались более гибкие совпадения, а теперь требуется строгое
соответствие только одной ветке.
В новых версиях изменён формат массива ошибок.
Ранее:
ajv.errors
мог содержать менее структурированную информацию.
Теперь:
instancePathschemaPath и keywordЭто упрощает диагностику, но требует адаптации обработчиков ошибок.
Внутренний механизм компиляции был существенно переработан:
if/thenОднако при миграции возможны ситуации, когда:
Миграция почти всегда сопровождается обновлением зависимостей:
ajv-formats для стандартных форматовajv-errors для кастомных сообщенийКаждый из них должен быть совместим с используемой версией ядра, иначе возможны ошибки регистрации ключевых слов.
На практике чаще всего возникают следующие ситуации:
coerceTypes отличается от ожидаемогоДля больших проектов применяется поэтапная стратегия:
Такой подход позволяет минимизировать разрыв между версиями и избежать массовых ошибок валидации на этапе обновления.