В процессе разработки систем валидации JSON-данных на базе Ajv неизбежно возникает необходимость изменять ранее введённые схемы, пользовательские ключевые слова и форматы. Такие изменения могут приводить к изменению поведения валидатора, что требует механизма возврата к предыдущему состоянию. Под откатом изменений в контексте Ajv понимается восстановление предыдущей конфигурации экземпляра валидатора или конкретных его компонентов без полной перезагрузки приложения.
Ajv позволяет динамически регистрировать схемы через механизм
addSchema. Каждая добавленная схема становится частью
внутреннего реестра и может быть использована для последующей
валидации.
Удаление ранее добавленной схемы выполняется через
removeSchema, что фактически возвращает состояние реестра к
моменту до регистрации этой схемы.
import Ajv from "ajv";
const ajv = new Ajv();
const schemaV1 = {
$id: "user-schema",
type: "object",
properties: {
name: { type: "string" }
},
required: ["name"]
};
ajv.addSchema(schemaV1);
// Откат схемы
ajv.removeSchema("user-schema");
Удаление схемы по идентификатору особенно важно при частых обновлениях контрактов API, где старые версии схем могут конфликтовать с новыми правилами валидации.
При удалении схемы важно учитывать, что уже скомпилированные валидаторы могут оставаться в памяти, если на них есть ссылки в коде.
Ajv компилирует схемы в функции-валидаторы. После компиляции результат может кешироваться и переиспользоваться.
const validate = ajv.compile(schemaV1);
Даже если схема удалена через removeSchema, переменная
validate продолжит работать, так как содержит уже
скомпилированную функцию. Это означает, что откат схемы не влияет на уже
созданные валидаторы.
Для полного отката поведения необходимо:
Ajv поддерживает расширение через пользовательские ключевые слова,
добавляемые методом addKeyword. Такие расширения часто
влияют на логику валидации, поэтому их удаление является частью
механизма отката.
ajv.addKeyword({
keyword: "isPositive",
type: "number",
validate: (schema, data) => data > 0
});
Удаление выполняется через removeKeyword:
ajv.removeKeyword("isPositive");
После удаления ключевого слова любые схемы, использующие его, перестают корректно валидироваться. При этом ранее скомпилированные валидаторы сохраняют прежнее поведение, что создаёт потенциальную несогласованность состояния.
Форматы в Ajv используются для валидации строковых значений
(например, email, uri и т.д.). Добавление кастомных форматов
осуществляется через addFormat.
ajv.addFormat("phone", {
type: "string",
validate: (value) => /^\+\d{10,15}$/.test(value)
});
Удаление формата возможно через removeFormat:
ajv.removeFormat("phone");
При откате формата необходимо учитывать, что:
В Ajv нет встроенного метода «reset», поэтому полный откат состояния достигается созданием нового экземпляра валидатора.
const ajv = new Ajv();
// при необходимости полного отката
const ajvNew = new Ajv();
Такой подход гарантирует:
Это наиболее надёжный способ вернуть валидатор к исходному состоянию.
Ajv активно использует кэширование для ускорения компиляции схем. Этот механизм влияет на процесс отката, поскольку:
Контроль кэша осуществляется через параметры конфигурации экземпляра:
const ajv = new Ajv({
cache: false
});
Отключение кэша позволяет добиться более предсказуемого поведения при частых откатах и изменениях схем, но снижает производительность.
Одним из практических подходов к управлению изменениями является хранение нескольких версий схем одновременно.
const schemaV1 = { $id: "user-v1", type: "object", properties: { name: { type: "string" } } };
const schemaV2 = { $id: "user-v2", type: "object", properties: { name: { type: "string" }, age: { type: "number" } } };
ajv.addSchema(schemaV1);
ajv.addSchema(schemaV2);
Откат в таком случае выполняется не удалением логики, а переключением на нужную версию схемы:
Удаление устаревших версий становится отдельной операцией очистки, а не частью отката.
Ajv поддерживает различные версии спецификации JSON Schema (draft-07, draft-2019-09, draft-2020-12). Изменение draft-версии может приводить к несовместимости схем.
const ajv = new Ajv({
schemaId: "auto"
});
При смене draft-версии возможны ситуации, когда:
if/then/else,
contains, dependentRequired)Откат в этом контексте фактически означает возврат к предыдущему экземпляру Ajv с нужной версией спецификации.
В динамических системах схемы могут изменяться во время работы приложения. В таких сценариях применяются следующие механизмы:
const schemaRegistry = {
active: schemaV2,
previous: schemaV1
};
// откат
schemaRegistry.active = schemaRegistry.previous;
Ajv в этом случае выступает только как механизм валидации, а управление версиями переносится на уровень архитектуры приложения.
При возврате к предыдущему состоянию часто возникают следующие несоответствия:
Эти эффекты делают невозможным частичный откат без учёта всей цепочки зависимостей внутри экземпляра Ajv.
Корректная стратегия отката требует синхронного управления всеми компонентами Ajv:
Нарушение согласованности приводит к расхождению между зарегистрированными схемами и фактической логикой валидации, что особенно критично в системах с долгоживущими экземплярами валидатора.