Валидация массивов в JSON Schema опирается на два принципиально разных подхода: одинаковая структура элементов и фиксированная позиционная структура. Второй подход реализует концепцию кортежей, где каждый индекс массива имеет строго определённое значение и собственную схему проверки. В библиотеке Ajv этот механизм поддерживается в полном объёме и особенно важен при работе с API, контрактами данных и строгими типами структур.
Кортежная модель массива отличается от обычной тем, что элементы не являются однородными. Каждый индекс рассматривается как отдельное поле с собственной схемой.
Пример концепции:
Такой массив уже не является коллекцией однотипных значений, а превращается в фиксированную структуру данных, аналогичную структурам или записям в других языках программирования.
В Ajv это используется для строгой валидации входящих данных, где порядок элементов имеет семантическое значение.
В более ранних версиях JSON Schema (draft-07 и ранее) кортежи описывались через массив схем внутри свойства items:
const schema = {
type: "array",
items: [
{ type: "string" },
{ type: "number" },
{ type: "boolean" }
]
};
Поведение такой схемы:
Если дополнительная логика не указана, то поведение зависит от
additionalItems.
Для кортежей важно контролировать поведение элементов за пределами
определённой длины. В старой модели используется
additionalItems:
const schema = {
type: "array",
items: [
{ type: "string" },
{ type: "number" }
],
additionalItems: false
};
В этом случае массив обязан содержать ровно два элемента. Любой третий элемент приводит к ошибке валидации.
Также возможен вариант с собственной схемой для дополнительных значений:
additionalItems: { type: "string" }
Тогда все элементы после фиксированной части должны соответствовать указанной схеме.
В спецификации JSON Schema 2020-12 поведение кортежей формализовано
через ключ prefixItems. Он отделяет фиксированную часть
массива от остальных элементов.
const schema = {
type: "array",
prefixItems: [
{ type: "string" },
{ type: "number" },
{ type: "boolean" }
]
};
Семантика:
prefixItemsitemsВ новой модели items больше не используется для описания
кортежа, а отвечает за хвостовую часть массива:
const schema = {
type: "array",
prefixItems: [
{ type: "string" },
{ type: "number" }
],
items: { type: "string" }
};
Поведение:
Такой подход делает структуру более читаемой и явно разделяет фиксированную и повторяющуюся части массива.
Ajv интерпретирует схемы в зависимости от версии спецификации. При
включённой поддержке draft-2020-12 используется
prefixItems, при более старых версиях — массив
items.
Внутренний механизм валидации:
additionalItems: falseОшибки формируются с указанием индекса, что критично для диагностики:
data[1] should be numberdata[2] should be booleanКортежи могут содержать неопределённые позиции. Это достигается через
null, anyOf или oneOf:
prefixItems: [
{ type: "string" },
{ type: ["number", "null"] },
{ type: "boolean" }
]
Такая конструкция позволяет моделировать частично заполненные структуры, сохраняя позиционную строгость.
Кортежи часто используются для описания протокольных данных:
const schema = {
type: "array",
prefixItems: [
{ const: "event" },
{ type: "string" },
{ type: "integer" },
{ type: "object" }
],
items: false
};
Здесь:
Отключение items: false запрещает любые дополнительные
данные, превращая массив в строго фиксированную запись.
Ключевое различие заключается в уровне абстракции:
Обычные массивы:
Кортежи:
Ajv использует это различие для генерации точных ошибок и оптимизации проверки.
Кортежи обрабатываются быстрее в сравнении с массивами с комплексными
условиями oneOf на каждый элемент, поскольку:
Особенно это заметно в больших JSON-документах с повторяющимися структурами.
Часто встречаются следующие проблемы:
items вместо prefixItems в
новых схемахitems, приводящий к неожиданным
дополнительным элементамAjv строго разделяет поведение в зависимости от версии спецификации, поэтому некорректная комбинация ключей приводит к непредсказуемой валидации.
Кортежи часто содержат сложные структуры:
prefixItems: [
{ type: "string" },
{
type: "object",
properties: {
id: { type: "number" },
name: { type: "string" }
},
required: ["id"]
}
]
Такая схема моделирует компактные протоколы обмена данными, где массив заменяет JSON-объект для уменьшения размера и ускорения парсинга.
Кортежные схемы особенно характерны для:
Ajv обеспечивает детерминированную проверку таких структур без необходимости дополнительных трансформаций данных.