Валидация элементов

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

Для включения валидации массива достаточно указать тип array. При этом проверка ограничивается лишь тем, что значение действительно является массивом JavaScript.

{
  "type": "array"
}

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

Дополнительные ограничения вводятся через ключевые слова items, minItems, maxItems, uniqueItems.


Однородные массивы и ключевое слово items

Наиболее распространённый сценарий — массив, где все элементы имеют одинаковую структуру. Для этого используется items как схема одного элемента.

{
  "type": "array",
  "items": {
    "type": "number"
  }
}

В таком случае каждый элемент массива проверяется по одной и той же схеме.

Пример допустимого значения:

[1, 2, 3, 4]

Пример недопустимого значения:

[1, "2", 3]

Ограничение количества элементов

Ключевые слова minItems и maxItems управляют длиной массива.

{
  "type": "array",
  "items": { "type": "string" },
  "minItems": 2,
  "maxItems": 5
}

Значения вне диапазона длины автоматически считаются невалидными.


Уникальность элементов

Ключ uniqueItems включает проверку уникальности всех элементов массива.

{
  "type": "array",
  "uniqueItems": true
}

При включении этого параметра происходит глубокое сравнение значений, включая объекты и массивы.

Примеры:

Допустимо:

[1, 2, 3]

Недопустимо:

[1, 1, 2]

Кортежи и позиционная валидация

В JSON Schema массив может рассматриваться как кортеж, где каждый индекс соответствует отдельной схеме. В Ajv это реализуется через массив схем в items.

{
  "type": "array",
  "items": [
    { "type": "string" },
    { "type": "number" },
    { "type": "boolean" }
  ]
}

В этом случае:

  • первый элемент должен быть строкой
  • второй — числом
  • третий — булевым значением

Пример валидного массива:

["id", 10, true]

Поведение при превышении длины кортежа

Если массив содержит больше элементов, чем определено в массиве схем items, поведение зависит от версии спецификации и дополнительных ключевых слов.

По умолчанию лишние элементы допускаются, если не ограничены additionalItems.


Ограничение дополнительных элементов

Ключ additionalItems управляет поведением элементов, выходящих за пределы описанного кортежа.

{
  "type": "array",
  "items": [
    { "type": "string" },
    { "type": "number" }
  ],
  "additionalItems": false
}

Здесь массив строго ограничен двумя элементами.

Пример допустимого значения:

["name", 42]

Недопустимое:

["name", 42, true]

Также additionalItems может быть схемой, применяемой ко всем дополнительным элементам:

"additionalItems": { "type": "string" }

Современный подход: prefixItems и дополнительные элементы

В более новых версиях JSON Schema используется prefixItems, которое заменяет поведение массива схем items.

{
  "type": "array",
  "prefixItems": [
    { "type": "string" },
    { "type": "number" }
  ],
  "items": { "type": "boolean" }
}

Здесь:

  • первые элементы проверяются строго по позициям
  • последующие должны быть булевыми значениями

Проверка наличия элементов через contains

Ключевое слово contains позволяет проверять наличие хотя бы одного элемента, соответствующего заданной схеме.

{
  "type": "array",
  "contains": {
    "type": "string",
    "pattern": "^A"
  }
}

Такой массив должен содержать хотя бы одну строку, начинающуюся с буквы A.

Пример валидного массива:

[1, "Apple", 3]

Ограничение количества совпадающих элементов

Дополнительные параметры:

  • minContains
  • maxContains
{
  "type": "array",
  "contains": { "type": "number" },
  "minContains": 2,
  "maxContains": 4
}

Это задаёт диапазон количества элементов, удовлетворяющих contains.


Комбинирование items и contains

Комбинация items и contains позволяет задавать как общую структуру массива, так и обязательное присутствие определённых элементов.

{
  "type": "array",
  "items": { "type": "number" },
  "contains": { "const": 0 }
}

Такой массив состоит из чисел и обязан содержать значение 0.


Вложенные массивы

Валидация может применяться рекурсивно:

{
  "type": "array",
  "items": {
    "type": "array",
    "items": { "type": "number" }
  }
}

Здесь задаётся структура матрицы — массив массивов чисел.

Пример валидного значения:

[[1, 2], [3, 4]]

Сложные структуры и комбинированные схемы

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

{
  "type": "array",
  "items": {
    "oneOf": [
      { "type": "string" },
      { "type": "number" }
    ]
  }
}

Каждый элемент массива может принадлежать к одному из допустимых типов.


Особенности проверки производительности

Валидация массивов может становиться ресурсоёмкой при:

  • использовании uniqueItems с объектами
  • глубоко вложенных структурах
  • комбинировании contains с большими массивами
  • применении сложных oneOf и anyOf

Оптимизация обычно достигается через:

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

Поведение при частичной валидации элементов

Внутренний механизм Ajv позволяет собирать информацию о том, какие элементы массива прошли проверку, если включён режим verbose или используется allErrors.

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


Индексация ошибок

При провале валидации массива ошибки обычно содержат:

  • индекс элемента
  • путь в данных (instancePath)
  • описание нарушенного ограничения

Пример структуры ошибки:

  • /0/type — ошибка в первом элементе
  • /2/contains — нарушение условия contains

Такая структура позволяет точно локализовать источник ошибки внутри массива.