Кратность: multiple

Валидация данных в реальных приложениях часто связана с обработкой коллекций, массивов и полей, допускающих несколько значений. В Joi такие сценарии реализуются через комбинирование Joi.array(), методов .items(), а также логики альтернатив и составных условий. Поддержка множественности охватывает не только массивы, но и сложные схемы с несколькими допустимыми типами и наборами правил.


Массивы как основной механизм множественности

Базовая конструкция для работы с множественными значениями строится вокруг Joi.array():

import Joi from 'joi';

const schema = Joi.array();

На этом уровне описывается только факт того, что значение должно быть массивом. Поведение элементов задаётся отдельно.


Метод items: определение структуры элементов

Метод .items() определяет, какие значения допустимы внутри массива. Это ключевой инструмент для работы с множественностью:

const schema = Joi.array().items(Joi.string());

В этом случае массив может содержать любое количество строк.

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

const schema = Joi.array().items(
  Joi.string(),
  Joi.number()
);

Такой вариант допускает массив, содержащий как строки, так и числа. Joi проверяет каждый элемент по всем указанным схемам.


Строгая типизация элементов

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

const schema = Joi.array().items(
  Joi.string().required(),
  Joi.number().integer().min(0)
);

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


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

Множественность часто сопровождается контролем размера коллекции:

const schema = Joi.array()
  .items(Joi.string())
  .min(1)
  .max(5);

Здесь задаётся диапазон допустимого количества элементов.


Уникальность значений

Для предотвращения дублирования используется .unique():

const schema = Joi.array()
  .items(Joi.string())
  .unique();

Каждое значение в массиве должно быть уникальным, что особенно важно для идентификаторов и списков ключей.


Разреженные массивы

По умолчанию Joi допускает undefined в массиве только при явной настройке:

const schema = Joi.array()
  .items(Joi.string())
  .sparse();

Это позволяет сохранять структуру массива с пропущенными значениями.


Альтернативные схемы для множественных форматов

Множественность может выражаться не только через массивы, но и через альтернативные типы данных:

const schema = Joi.alternatives().try(
  Joi.string(),
  Joi.array().items(Joi.string())
);

Такое определение допускает как одиночное значение, так и массив значений одного типа.


Логические операторы множественных условий

Joi предоставляет инструменты для построения сложных правил, связанных с множественными полями или значениями.

OR-условие

const schema = Joi.object({
  email: Joi.string(),
  phone: Joi.string()
}).or('email', 'phone');

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


AND-условие

const schema = Joi.object({
  a: Joi.number(),
  b: Joi.number()
}).and('a', 'b');

Оба поля должны присутствовать одновременно.


XOR-условие

const schema = Joi.object({
  token: Joi.string(),
  password: Joi.string()
}).xor('token', 'password');

Допускается только одно из полей, но не оба сразу.


NAND-условие

const schema = Joi.object({
  admin: Joi.boolean(),
  debug: Joi.boolean()
}).nand('admin', 'debug');

Запрещается одновременное присутствие указанных полей.


Множественные правила внутри одного поля

Одно поле может подчиняться нескольким независимым ограничениям:

const schema = Joi.string()
  .min(3)
  .max(30)
  .pattern(/^[a-z]+$/);

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


Композиция массивов и объектов

Множественность часто проявляется в сложных структурах:

const schema = Joi.array().items(
  Joi.object({
    id: Joi.number().required(),
    tags: Joi.array().items(Joi.string()).unique()
  })
);

Каждый элемент массива представляет собой объект с собственными множественными полями.


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

Поддерживаются многомерные структуры:

const schema = Joi.array().items(
  Joi.array().items(Joi.number())
);

Такая схема описывает массив массивов чисел.


Комбинирование альтернатив и массивов

Расширенные сценарии включают смешение одиночных и множественных значений:

const schema = Joi.object({
  values: Joi.alternatives().try(
    Joi.number(),
    Joi.array().items(Joi.number())
  )
});

Поле может быть как числом, так и массивом чисел.


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

При работе с массивами Joi может возвращать несколько ошибок одновременно. Управление этим поведением зависит от конфигурации:

const schema = Joi.array()
  .items(Joi.string().min(5))
  .options({ abortEarly: false });

В таком режиме проверяются все элементы массива, а не останавливается при первой ошибке.


Кастомные проверки для множественных значений

При необходимости применяется .custom():

const schema = Joi.array().custom((value, helpers) => {
  if (value.length > 10) {
    return helpers.error('array.tooMany');
  }
  return value;
});

Логика может учитывать взаимосвязи между элементами массива, а не только их индивидуальные свойства.


Динамическая множественность через when

Условия позволяют менять структуру массива в зависимости от контекста:

const schema = Joi.object({
  type: Joi.string(),
  values: Joi.array().items(Joi.any()).when('type', {
    is: 'numbers',
    then: Joi.array().items(Joi.number()),
    otherwise: Joi.array().items(Joi.string())
  })
});

Один и тот же массив может иметь разные правила проверки.


Объединение множественных схем

Сложные структуры часто строятся через композицию:

const baseArray = Joi.array().items(Joi.string());

const extended = baseArray
  .min(2)
  .unique()
  .required();

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


Множественность на уровне API данных

Валидация множественных значений особенно важна в REST и GraphQL API, где:

  • списки идентификаторов передаются в query-параметрах,
  • batch-запросы содержат массивы сущностей,
  • фильтры используют наборы значений.

Joi обеспечивает единообразную проверку таких структур без необходимости ручной обработки данных перед валидацией.