Создание простых схем

Библиотека Joi предоставляет декларативный способ описания структуры данных и правил их валидации. В основе работы лежит понятие схемы — объекта, который описывает ожидаемую форму данных и ограничения для каждого поля.

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


Базовая структура схемы объекта

Наиболее часто используемая форма — объектная схема, создаваемая через Joi.object().

const Joi = require('joi');

const schema = Joi.object({
  name: Joi.string(),
  age: Joi.number(),
  email: Joi.string()
});

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

  • name — строка
  • age — число
  • email — строка

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


Обязательные поля

По умолчанию все поля считаются необязательными. Для указания обязательности используется метод required().

const schema = Joi.object({
  name: Joi.string().required(),
  age: Joi.number().required(),
  email: Joi.string()
});

В этом случае отсутствие name или age приведёт к ошибке валидации.


Ограничения строковых значений

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

const schema = Joi.object({
  username: Joi.string()
    .min(3)
    .max(30)
    .alphanum()
    .required()
});

Используемые методы:

  • min(n) — минимальная длина строки
  • max(n) — максимальная длина строки
  • alphanum() — только буквы и цифры

Дополнительно часто применяется проверка на email:

const schema = Joi.object({
  email: Joi.string()
    .email()
    .required()
});

Метод email() проверяет соответствие стандартному формату электронной почты.


Числовые ограничения

Для числовых значений применяются диапазоны и дополнительные проверки.

const schema = Joi.object({
  age: Joi.number()
    .integer()
    .min(0)
    .max(120)
});

Основные методы:

  • integer() — только целые числа
  • min(n) — минимальное значение
  • max(n) — максимальное значение

Также возможна проверка на положительные или отрицательные числа:

const schema = Joi.object({
  score: Joi.number().positive(),
  debt: Joi.number().negative()
});

Логические значения

Булевы поля описываются через Joi.boolean().

const schema = Joi.object({
  isActive: Joi.boolean(),
  isAdmin: Joi.boolean().required()
});

Допустимые значения автоматически приводятся к логическому типу при включённых опциях преобразования.


Работа с вложенными объектами

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

const schema = Joi.object({
  user: Joi.object({
    name: Joi.string().required(),
    age: Joi.number().required()
  }),
  isActive: Joi.boolean()
});

Каждый уровень вложенности также описывается через Joi.object().


Списки и массивы

Для описания массивов используется Joi.array() с указанием типа элементов.

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

Метод items() задаёт схему элементов массива.

Дополнительно могут применяться ограничения:

const schema = Joi.object({
  tags: Joi.array()
    .items(Joi.string())
    .min(1)
    .max(5)
});

Значения по умолчанию

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

const schema = Joi.object({
  role: Joi.string().default('user'),
  isActive: Joi.boolean().default(true)
});

Метод default() определяет значение, используемое при отсутствии поля.


Запрещённые значения

В некоторых случаях требуется исключить определённые значения.

const schema = Joi.object({
  role: Joi.string().invalid('admin', 'superuser')
});

Метод invalid() запрещает указанные значения.

Альтернативный вариант — использование valid() для перечисления допустимых значений:

const schema = Joi.object({
  role: Joi.string().valid('user', 'moderator', 'guest')
});

Гибкие схемы с любыми ключами

Иногда структура объекта неизвестна заранее. Для таких случаев применяется unknown(true).

const schema = Joi.object({
  name: Joi.string()
}).unknown(true);

Такой подход разрешает наличие дополнительных полей, не описанных в схеме.


Минимальные схемы без объектной структуры

Схемы могут использоваться и без Joi.object(), описывая отдельные значения.

const schema = Joi.string().min(5).max(10);

Или:

const schema = Joi.number().integer().positive();

Такие схемы применяются для проверки одиночных значений, например параметров URL или отдельных полей запроса.


Комбинирование правил

Методы Joi поддерживают цепочки вызовов, позволяя комбинировать ограничения в одном выражении.

const schema = Joi.object({
  password: Joi.string()
    .min(8)
    .max(64)
    .pattern(/^[a-zA-Z0-9!@#\$%\^&\*]+$/)
    .required()
});

Метод pattern() добавляет регулярное выражение для проверки строки.


Схемы с альтернативами

Для случаев, когда допустимы разные типы данных, используется alternatives().

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

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