Метод allow() в Joi расширяет допустимое множество
значений для схемы валидации. Его ключевая задача — добавить
«исключения» к уже существующим ограничениям, позволяя пройти валидацию
значениям, которые иначе были бы отвергнуты базовой схемой.
В Joi любая схема изначально задаёт набор правил. Например:
const schema = Joi.string().min(3);
Такое правило допускает только строки длиной от 3 символов и выше.
Попытка передать "" (пустую строку) приведёт к ошибке.
Использование allow() изменяет поведение:
const schema = Joi.string().min(3).allow('');
Теперь пустая строка становится допустимой, несмотря на то, что она
нарушает правило min(3).
Важно понимать ключевую особенность: allow() не убирает
существующие ограничения, а добавляет дополнительные разрешённые
значения.
Метод принимает несколько аргументов:
const schema = Joi.number().min(10).allow(null, 0);
В этом случае допустимыми становятся:
null0Даже если 0 не проходит проверку min(10),
оно всё равно допускается.
allow() способен «пробить» типовые ограничения:
const schema = Joi.number().allow('unknown');
Хотя схема ожидает число, строка 'unknown' также
становится допустимой.
Это поведение часто используется для обработки служебных значений, приходящих из внешних систем, где тип данных может быть нестабильным.
allow() не подменяет значение и не задаёт значение по
умолчанию. Следующий пример:
const schema = Joi.string().allow(null);
означает, что null допустим, но не заменяется на строку
и не трансформируется.
Метод valid() задаёт строгое перечисление допустимых
значений. В отличие от allow(), он не расширяет
существующие правила, а заменяет их ограниченным набором.
const schema = Joi.string().valid('admin', 'user', 'guest');
Теперь допустимы только три строки:
adminuserguestЛюбое другое значение вызовет ошибку валидации.
valid() фактически выполняет роль перечисления
(enum):
const schema = Joi.number().valid(1, 2, 3);
Допустимы только значения 1, 2,
3. Даже если число соответствует другим условиям схемы, но
не входит в список, оно будет отклонено.
Ключевая особенность valid() — полное перекрытие других
правил:
const schema = Joi.number().min(10).valid(5, 20);
В этом случае:
min(10) фактически перестаёт влиять на значение
55 и 20То есть valid() имеет приоритет над другими
ограничениями в контексте допустимых значений.
В некоторых версиях Joi присутствует алиас:
Joi.string().only()
Он эквивалентен:
Joi.string().valid(...)
allow() — добавляет исключения к правиламvalid() — задаёт строгий список допустимых
значенийJoi.number().min(10).allow(5)
Значение 5 проходит, несмотря на
min(10).
Joi.number().min(10).valid(5)
Значение 5 также проходит, но только потому, что входит
в список допустимых значений. Любое другое число вне списка будет
отклонено, даже если оно соответствует min(10).
allow() расширяет пространство допустимых значенийvalid() сужает пространство допустимых значений до
перечисленияJoi.string().allow(null)
Разрешает null, даже если строка не допускает
null по умолчанию.
Joi.string().valid(null)
Означает, что единственным допустимым значением может быть только
null.
Если добавить строку:
Joi.string().valid(null, 'text')
то допустимыми становятся только null и
'text'.
Методы могут использоваться совместно:
const schema = Joi.string().valid('a', 'b').allow('');
Логика обработки:
valid('a', 'b') ограничивает значения до a
и ballow('') добавляет пустую строку как дополнительное
допустимое значениеИтоговый набор допустимых значений: a, b,
''.
Joi.array().items(Joi.number().valid(1, 2)).allow(null)
Допустимы:
nullconst schema = Joi.object({
role: Joi.string().valid('admin', 'user').allow('guest')
});
Здесь:
admin и user допустимы по
validguest добавлен через allowПри нарушении valid() обычно возвращается ошибка:
"value" must be one of [a, b, c]
allow() не вызывает ошибку для добавленных значений,
поэтому сообщения об ошибке относятся только к базовым ограничениям
схемы.
Joi.string().valid('active', 'inactive').allow('unknown')
Используется при миграции систем, где старые данные не соответствуют новой модели.
Joi.number().min(0).allow(-1)
Часто -1 используется как служебное значение “не
задано”.
Joi.alternatives().try(
Joi.string().valid('auto', 'manual'),
Joi.number().allow(0)
)
Позволяет комбинировать строгие и расширенные правила в одной структуре.
Joi.string().allow('admin')
Такое использование не ограничивает значение только
'admin', а лишь добавляет его как допустимое. Любая строка
остаётся допустимой, если нет других ограничений.
Joi.number().valid(10).min(100)
Несмотря на min(100), значение 10 всё равно
будет допустимо, потому что valid() переопределяет
допустимые значения.
Использование allow() и valid() без чёткого
понимания приоритетов может привести к неожиданным результатам, когда
схема допускает больше значений, чем предполагается.
Внутренняя логика Joi при обработке этих методов строится так:
valid() формирует набор разрешённых значенийallow() добавляет дополнительные исключенияvalid() или
allow()Таким образом:
valid() задаёт жёсткий фильтрallow() расширяет набор допустимых значений поверх
фильтрацииconst base = Joi.string().min(3);
const extended = base.allow('').valid('admin', 'user', '');
Здесь формируется гибрид:
admin, userТакие композиции часто применяются в модульных схемах, где базовая логика переиспользуется и расширяется в зависимости от контекста.