Валидация данных в реальных приложениях часто связана с обработкой
коллекций, массивов и полей, допускающих несколько значений. В Joi такие
сценарии реализуются через комбинирование Joi.array(),
методов .items(), а также логики альтернатив и составных
условий. Поддержка множественности охватывает не только массивы, но и
сложные схемы с несколькими допустимыми типами и наборами правил.
Базовая конструкция для работы с множественными значениями строится
вокруг Joi.array():
import Joi from 'joi';
const schema = Joi.array();
На этом уровне описывается только факт того, что значение должно быть массивом. Поведение элементов задаётся отдельно.
Метод .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 предоставляет инструменты для построения сложных правил, связанных с множественными полями или значениями.
const schema = Joi.object({
email: Joi.string(),
phone: Joi.string()
}).or('email', 'phone');
Объект считается валидным, если присутствует хотя бы одно из полей.
const schema = Joi.object({
a: Joi.number(),
b: Joi.number()
}).and('a', 'b');
Оба поля должны присутствовать одновременно.
const schema = Joi.object({
token: Joi.string(),
password: Joi.string()
}).xor('token', 'password');
Допускается только одно из полей, но не оба сразу.
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;
});
Логика может учитывать взаимосвязи между элементами массива, а не только их индивидуальные свойства.
Условия позволяют менять структуру массива в зависимости от контекста:
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();
Схемы можно переиспользовать, расширяя поведение без дублирования логики.
Валидация множественных значений особенно важна в REST и GraphQL API, где:
Joi обеспечивает единообразную проверку таких структур без необходимости ручной обработки данных перед валидацией.