Управление ошибками

Валидация в Ajv строится вокруг детализированного описания каждой ошибки, возникающей при проверке данных на соответствие JSON Schema. Каждая ошибка представляет собой объект с набором полей, позволяющих точно определить источник несоответствия и контекст его возникновения.

Ключевые поля объекта ошибки:

  • instancePath — путь к элементу входных данных, где произошло нарушение
  • schemaPath — путь к правилу схемы, которое не было выполнено
  • keyword — тип проверочного правила (например, type, minLength, required)
  • message — человекочитаемое описание ошибки
  • params — дополнительные параметры, зависящие от конкретного keyword

Пример типичной ошибки:

{
  instancePath: "/age",
  schemaPath: "#/properties/age/minimum",
  keyword: "minimum",
  message: "must be >= 18",
  params: {
    comparison: ">=",
    limit: 18
  }
}

Такая структура позволяет не только сообщить о факте ошибки, но и точно локализовать её в данных и в схеме.

Механизм формирования массива ошибок

По умолчанию Ajv может прерывать проверку при первой найденной ошибке, однако чаще используется режим накопления всех нарушений.

Ключевая опция:

  • allErrors: true — включает сбор всех ошибок, а не только первой

При включённой опции валидатор продолжает обход схемы даже после обнаружения несоответствий, формируя массив errors.

const validate = ajv.compile(schema);

validate(data);

console.log(validate.errors);

Каждый элемент массива соответствует отдельному нарушению.

Поведение при остановке на первой ошибке

При allErrors: false (значение по умолчанию в некоторых конфигурациях) выполнение прерывается, как только обнаружено первое несоответствие. Это уменьшает накладные расходы, но ограничивает диагностическую информацию.

Такой режим используется в сценариях:

  • быстрых проверок входных данных
  • API с минимальной диагностикой
  • критичных по производительности системах

Ключ keyword и его роль в диагностике

Поле keyword определяет тип проверки, которая не была пройдена. Оно напрямую связано с логикой JSON Schema.

Часто встречающиеся значения:

  • type — несоответствие типу данных
  • required — отсутствие обязательного поля
  • minimum / maximum — нарушение числовых ограничений
  • minLength / maxLength — нарушение длины строки
  • pattern — несоответствие регулярному выражению
  • enum — значение не входит в допустимый набор

Анализ keyword позволяет группировать ошибки по типам и строить централизованную обработку.

instancePath и навигация по данным

instancePath описывает путь в проверяемом объекте в формате JSON Pointer.

Примеры:

  • /user/name
  • /items/0/price
  • /address/city

Этот путь используется для:

  • формирования сообщений пользователю
  • построения UI-валидации форм
  • автоматического подсвечивания полей

При глубокой вложенности объектов instancePath становится основным инструментом локализации ошибки.

schemaPath и диагностика схем

Поле schemaPath указывает на конкретное правило внутри JSON Schema, которое было нарушено. Оно полезно при отладке сложных схем, особенно при их генерации или композиции через allOf, oneOf, anyOf.

Пример:

#/properties/user/properties/email/pattern

Это позволяет точно определить, какое ограничение сработало.

Формирование человекочитаемых сообщений

Поле message генерируется Ajv автоматически на основе keyword и параметров ошибки.

Примеры:

  • “must be string”
  • “must have required property ‘id’”
  • “must match pattern”1+$“”

Стандартные сообщения часто недостаточны для пользовательских интерфейсов, поэтому применяется их переопределение.

Параметры ошибок (params)

Поле params содержит контекст, необходимый для интерпретации ошибки.

Примеры:

minimum

params: { limit: 10 }

required

params: { missingProperty: "email" }

pattern

params: { pattern: "^[0-9]+$" }

Это поле используется для генерации кастомных сообщений и бизнес-логики обработки.

Кастомизация сообщений об ошибках

Ajv поддерживает переопределение сообщений через несколько механизмов.

Использование ajv-errors

Плагин позволяет задавать собственные сообщения прямо в схеме:

const schema = {
  type: "object",
  properties: {
    age: {
      type: "number",
      errorMessage: "Возраст должен быть числом"
    }
  }
};

Такой подход переносит ответственность за текст ошибки ближе к схеме.

Функциональная трансформация ошибок

После валидации ошибки могут быть преобразованы:

const errors = validate.errors.map(err => ({
  field: err.instancePath,
  rule: err.keyword,
  message: err.message
}));

Это распространённый паттерн для API-слоёв.

Нормализация ошибок для API

В серверных приложениях ошибки Ajv часто приводятся к унифицированному формату:

{
  field: "age",
  code: "MINIMUM",
  message: "Age must be at least 18"
}

Процесс нормализации включает:

  • удаление технических полей (schemaPath)
  • преобразование instancePath в ключ поля
  • маппинг keyword в код ошибки

Группировка ошибок

При большом количестве нарушений полезно группировать ошибки по полям:

const grouped = validate.errors.reduce((acc, err) => {
  const field = err.instancePath || "root";
  acc[field] = acc[field] || [];
  acc[field].push(err.message);
  return acc;
}, {});

Результат удобен для отображения в формах.

Ошибки вложенных структур

Для массивов и объектов с глубокой вложенностью Ajv формирует сложные пути:

  • /users/3/email
  • /orders/0/items/2/price

Корректная обработка таких путей требует парсинга instancePath и сопоставления с UI-компонентами.

Режим строгой валидации и ошибки схемы

Ajv также генерирует ошибки не только данных, но и схемы:

  • некорректные типы в schema
  • конфликтующие ключи
  • нарушение режима strict

Такие ошибки доступны через отдельные механизмы логирования и опции strict.

Производительность обработки ошибок

Сбор ошибок влияет на производительность:

  • allErrors: false — минимальная нагрузка
  • allErrors: true — линейный рост затрат в зависимости от числа нарушений

В сложных схемах с oneOf и anyOf стоимость может существенно возрастать из-за повторных проверок.

Контекстная интерпретация ошибок

Валидация часто зависит от контекста:

  • условные схемы (if/then/else)
  • зависимости (dependentRequired)
  • динамические ключи (patternProperties)

В таких случаях instancePath и schemaPath дополняются контекстом ветвления схемы, что усложняет интерпретацию ошибки.

Логирование и трассировка

В системах с распределённой архитектурой ошибки Ajv часто записываются в лог с дополнительными полями:

  • идентификатор запроса
  • версия схемы
  • входные данные (частично)
  • результат валидации

Это позволяет отслеживать деградацию данных и изменения контрактов API.

Интеграция с пользовательскими интерфейсами

Ошибки Ajv используются в формах для:

  • подсветки полей
  • отображения подсказок
  • блокировки отправки данных

Типичный маппинг:

  • instancePath → поле формы
  • message → текст ошибки
  • keyword → тип валидационного правила

Такая модель позволяет унифицировать клиентскую и серверную валидацию.


  1. a-z↩︎