Методы валидации: validate, attempt, assert

В библиотеке Joi ключевая роль отводится механизмам проверки данных, которые позволяют описывать схемы и применять их к входящим значениям. Среди наиболее используемых методов выделяются validate, attempt и assert. Несмотря на общую цель — валидацию, каждый из них отличается поведением, уровнем строгости и способом обработки ошибок.


validate

Метод validate является базовым инструментом проверки данных. Он выполняет сравнение входного значения со схемой и возвращает результат без прерывания выполнения программы.

Общая сигнатура

Joi.validate(value, schema, [options], [callback])

Современные версии чаще используют:

schema.validate(value, options)

Структура результата

Результат работы validate представляет собой объект:

  • value — преобразованное и валидированное значение
  • error — объект ошибки (если валидация не прошла)
  • warning (в некоторых конфигурациях) — предупреждения

Пример использования

import Joi from 'joi';

const schema = Joi.object({
  username: Joi.string().min(3).max(30),
  age: Joi.number().integer().min(0)
});

const result = schema.validate({
  username: 'alex',
  age: 25
});

Поведение при ошибках

Если данные не соответствуют схеме, метод не выбрасывает исключение, а возвращает его в поле error.

const result = schema.validate({
  username: 'a',
  age: -5
});

if (result.error) {
  console.log(result.error.details);
}

Особенности

  • Не прерывает выполнение программы
  • Подходит для ручной обработки ошибок
  • Позволяет гибко управлять логикой валидации
  • Используется в большинстве API-слоёв и middleware

Опции validate

Метод поддерживает конфигурацию поведения:

  • abortEarly: false — возвращает все ошибки сразу
  • convert: true — преобразует типы (например, строки в числа)
  • allowUnknown: true — разрешает неизвестные поля
  • stripUnknown: true — удаляет лишние поля
schema.validate(data, { abortEarly: false, convert: true });

attempt

Метод attempt выполняет валидацию с более строгой моделью поведения. В случае ошибки он сразу выбрасывает исключение, а не возвращает объект результата.


Общая концепция

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


Сигнатура

schema.attempt(value, [options])

Пример использования

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

const data = schema.attempt({
  id: 10,
  name: 'product'
});

Если данные корректны, возвращается валидированное значение. Если нет — выполнение прерывается исключением.


Поведение при ошибке

schema.attempt({
  id: 'wrong',
  name: 'product'
});

В этом случае будет выброшено исключение, содержащее информацию о несоответствии схемы.


Отличия от validate

  • validate возвращает результат с ошибкой
  • attempt выбрасывает исключение
  • attempt не требует проверки if (error)

Области применения

  • Инициализация конфигураций
  • Проверка входных параметров функций
  • Жёсткие контракты между модулями
  • Сценарии, где дальнейшее выполнение невозможно при ошибке данных

Особенности

  • Более строгая модель контроля
  • Упрощает код за счёт отсутствия ручной обработки ошибок
  • Требует использования try/catch при необходимости безопасной обработки
try {
  const result = schema.attempt(input);
} catch (err) {
  console.error(err.message);
}

assert

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


Сигнатура

schema.assert(value, [message], [options])

Пример использования

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

schema.assert({
  email: 'test@example.com'
});

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


Поведение при ошибке

schema.assert({
  email: 'invalid-email'
});

Выбрасывается исключение с описанием ошибки валидации.


Кастомизация сообщения

schema.assert(
  { email: 'invalid' },
  'Некорректные входные данные'
);

При ошибке будет использовано указанное сообщение вместо стандартного.


Сравнение с attempt

Характеристика assert attempt
Возврат значения нет да
Исключение при ошибке да да
Возможность кастомного сообщения да ограниченно
Использование результата отсутствует присутствует

Сценарии применения

  • Проверка критических данных на входе приложения
  • Защита внутренних инвариантов
  • Контроль состояния системы
  • Валидация параметров, при которых продолжение невозможно

Особенности поведения

  • Не возвращает валидированное значение
  • Используется как «сторожевой механизм»
  • Повышает читаемость кода в местах строгих контрактов

Сравнительная модель поведения методов

Уровень строгости

  • validate — мягкая проверка
  • attempt — строгая проверка с возвратом результата
  • assert — строгая проверка без возврата результата

Управление ошибками

  • validate — ручная обработка через объект результата
  • attempt — автоматическое исключение
  • assert — автоматическое исключение без результата

Типовые сценарии выбора

validate

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

attempt

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

assert

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


Поведение преобразований и схем

Все три метода работают поверх одной и той же схемы Joi. Это означает, что:

  • преобразования типов применяются одинаково
  • правила валидации идентичны
  • различие заключается только в способе возврата результата и обработки ошибок

Влияние опций на методы

Опции схемы влияют на все методы одинаково:

  • stripUnknown влияет на финальный объект
  • convert изменяет типы входных данных
  • presence управляет обязательностью полей
  • abortEarly влияет только на validate

Ошибки и их структура

Во всех трёх методах ошибки имеют унифицированную структуру:

  • message — текст ошибки
  • details — массив описаний конкретных нарушений
  • path — путь к полю, где произошла ошибка
  • type — тип нарушения правила

Производственные сценарии использования

В серверной разработке методы распределяются по слоям архитектуры:

  • validate — API слой (обработка запросов)
  • attempt — бизнес-логика (гарантированные данные)
  • assert — системные инварианты и конфигурации

Типичные ошибки при использовании

Игнорирование результата validate

schema.validate(data);
// отсутствие проверки error приводит к некорректному состоянию

Использование attempt без try/catch

schema.attempt(data); // потенциальный runtime crash

assert в пользовательском вводе

Использование assert для пользовательских данных приводит к резкому завершению выполнения без возможности корректной обработки ошибок на уровне UI или API.


Итоговая модель взаимодействия методов

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

  • первый уровень — сбор и анализ (validate)
  • второй уровень — строгая обработка с результатом (attempt)
  • третий уровень — жёсткое подтверждение инвариантов (assert)