Отладка схем

Библиотека Ajv предоставляет детализированную систему валидации JSON-схем, где ключевым элементом отладки становится структура возвращаемых ошибок. При неуспешной валидации метод validate возвращает false, а подробности содержатся в validate.errors.

Каждая ошибка представляет собой объект с полями:

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

Пример:

const validate = ajv.compile(schema);

const valid = validate(data);

if (!valid) {
  console.log(validate.errors);
}

Интерпретация instancePath и schemaPath

instancePath указывает на конкретное место в проверяемом объекте данных. schemaPath указывает на участок схемы, который вызвал ошибку.

Пример:

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

Такая связка позволяет точно сопоставить:

  • где ошибка в данных
  • какое правило схемы её вызвало

Режимы расширенной диагностики

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

allErrors

По умолчанию валидация может останавливаться на первой ошибке. Режим allErrors заставляет продолжать проверку:

const ajv = new Ajv({ allErrors: true });

Это критически важно при отладке сложных схем, где необходимо видеть полный список проблем.


strict режим

Строгий режим помогает выявлять ошибки в самой схеме, а не только в данных:

const ajv = new Ajv({ strict: true });

Он контролирует:

  • неизвестные ключевые слова
  • некорректные типы схем
  • потенциально ошибочные конструкции

Дополнительно:

const ajv = new Ajv({
  strictTypes: true,
  strictTuples: true,
  strictRequired: true
});

Ошибки компиляции схемы

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

try {
  const validate = ajv.compile(schema);
} catch (err) {
  console.error(err.message);
}

Типичные причины:

  • опечатки в ключевых словах
  • неправильная структура JSON Schema
  • использование неподдерживаемых форматов

Чтение ошибок через errorsText

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

import Ajv from "ajv";

const ajv = new Ajv({ allErrors: true });

const validate = ajv.compile(schema);

if (!validate(data)) {
  console.log(ajv.errorsText(validate.errors));
}

Функция агрегирует ошибки в читаемый текст, но теряет структурированность.


Включение подробного вывода ошибок

Ajv позволяет включать расширенную информацию об ошибках:

const ajv = new Ajv({
  verbose: true
});

В этом режиме добавляются дополнительные поля:

  • data
  • parentSchema
  • dataPath (в старых версиях)

Это полезно при глубокой диагностике сложных схем.


Отладка через компиляцию функций

Ajv компилирует схемы в оптимизированные функции JavaScript. Их можно исследовать:

const validate = ajv.compile(schema);

console.log(validate.toString());

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

  • сгенерированный код проверки
  • порядок условий
  • оптимизации движка

При сложных схемах это часто быстрее выявляет проблему, чем анализ errors.


Использование logger для диагностики

Ajv поддерживает подключение логгера:

const ajv = new Ajv({
  logger: console
});

Он позволяет отслеживать:

  • предупреждения о схемах
  • deprecated-ключевые слова
  • нарушения strict-режима

Отладка $data ссылок

Механизм $data позволяет ссылаться на значения внутри данных:

const schema = {
  properties: {
    min: { type: "number" },
    value: {
      type: "number",
      minimum: { $data: "1/min" }
    }
  }
};

Ошибки в таких схемах часто связаны с:

  • неверным JSON pointer
  • отсутствием поля-источника
  • несовместимостью типов

При отладке важно проверять:

  • доступность пути $data
  • тип возвращаемого значения

Асинхронная валидация и ошибки

При использовании async-схем:

const validate = ajv.compileAsync(schema);

validate(data)
  .then(valid => {})
  .catch(err => {
    console.error(err);
  });

Ошибки могут быть двух типов:

  • ошибки схемы (compile-time)
  • ошибки промиса (runtime)

Особое внимание требуется при format с асинхронной проверкой.


Отладка пользовательских keywords

Ajv позволяет добавлять кастомные ключевые слова:

ajv.addKeyword({
  keyword: "even",
  validate: (schema, data) => data % 2 === 0
});

При отладке важно учитывать:

  • корректность регистрации keyword
  • порядок выполнения валидаторов
  • влияние errors внутри custom keyword

Для диагностики полезно временно расширять валидатор:

validate.errors = [];

или добавлять логирование внутри функции validate.


Частые проблемы при отладке схем

Несоответствие типов

Одна из наиболее частых проблем:

{ "type": "string" }

при передаче числа приводит к ошибке type.


Неучтённые required поля

{
  "required": ["id"]
}

Отсутствие поля приводит к ошибке required.


Конфликты oneOf / anyOf

Сложные конструкции:

  • oneOf требует ровно одну валидную схему
  • anyOf допускает несколько

Ошибки часто возникают из-за перекрытия условий.


Неявные преобразования типов

Ajv может не приводить типы автоматически:

const ajv = new Ajv({ coerceTypes: true });

Без этого числовые строки "123" будут считаться ошибкой.


Использование instance для пошаговой диагностики

Создание экземпляра Ajv с расширенной конфигурацией облегчает локализацию ошибок:

const ajv = new Ajv({
  allErrors: true,
  strict: true,
  verbose: true,
  logger: console,
  coerceTypes: false
});

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