Валидация в Joi не ограничивается проверкой типов и ограничений. Существенная часть работы библиотеки — управление тем, какие поля остаются в результате после валидации, а какие должны быть удалены. Это особенно важно при работе с API, где входящие данные часто содержат лишние или потенциально опасные поля.
Механизм strip позволяет явно указать, что конкретное
поле должно быть удалено из результата после успешной валидации, даже
если оно прошло проверку.
const Joi = require('joi');
const schema = Joi.object({
username: Joi.string().min(3).required(),
password: Joi.string().min(6).required(),
role: Joi.string().valid('user', 'admin').strip()
});
const result = schema.validate({
username: 'alex',
password: '123456',
role: 'admin'
});
console.log(result.value);
Результат:
{
username: 'alex',
password: '123456'
}
Поле role прошло валидацию, но было удалено из итогового
объекта.
strip() не влияет на процесс проверки значенияvalueconst schema = Joi.object({
id: Joi.number().integer().required(),
email: Joi.string().email().required(),
internalFlag: Joi.boolean().strip(),
debugInfo: Joi.string().strip()
});
В результате остаются только id и email,
остальные поля исчезают независимо от их валидности.
Помимо точечного strip, Joi поддерживает удаление всех
неизвестных ключей через опцию stripUnknown.
const schema = Joi.object({
name: Joi.string().required()
}).options({ stripUnknown: true });
const result = schema.validate({
name: 'John',
age: 30,
city: 'Astana'
});
Результат:
{
name: 'John'
}
Все поля, не описанные в схеме, удаляются автоматически.
При одновременном использовании действуют оба механизма:
const schema = Joi.object({
name: Joi.string().required(),
token: Joi.string().strip()
}).options({ stripUnknown: true });
Вход:
{
name: 'Anna',
token: 'secret',
role: 'admin'
}
Результат:
{
name: 'Anna'
}
role удалён как неизвестныйtoken удалён по явному правилу
.strip()Механизм keep используется как противоположность
strip. Он гарантирует, что поле не будет удалено даже в
случаях, когда включено глобальное удаление неизвестных значений.
const schema = Joi.object({
name: Joi.string().required(),
meta: Joi.object().unknown(true).keep()
}).options({ stripUnknown: true });
const result = schema.validate({
name: 'Ivan',
meta: {
ip: '127.0.0.1',
session: 'abc123'
}
});
Результат:
{
name: 'Ivan',
meta: {
ip: '127.0.0.1',
session: 'abc123'
}
}
Несмотря на stripUnknown, объект meta
сохранён полностью.
keep применяется в случаях, когда:
При конфликте правил действует следующая логика:
strip() имеет приоритет над глобальным сохранениемkeep() может переопределить stripUnknown,
но не отменяет явный .strip() на полеconst schema = Joi.object({
data: Joi.string().strip().keep()
}).options({ stripUnknown: true });
Поле data будет удалено, потому что:
.strip() имеет более высокий приоритет, чем
.keep()const schema = Joi.object({
user: Joi.object({
id: Joi.number().required(),
password: Joi.string().strip()
})
});
Результат:
{
user: {
id: 1
}
}
Удаление применяется на уровне вложенной структуры без дополнительной настройки.
Комбинация strip, keep и
stripUnknown часто используется для построения безопасного
слоя валидации входящих данных:
const schema = Joi.object({
username: Joi.string().required(),
password: Joi.string().required(),
role: Joi.string().valid('user', 'admin').strip(),
meta: Joi.object().unknown(true).keep()
}).options({ stripUnknown: true });
Такая схема обеспечивает:
Важно учитывать, что Joi сначала приводит данные к валидной форме
(coercion), и только затем применяет strip.
const schema = Joi.object({
age: Joi.number().strip()
});
const result = schema.validate({ age: '25' });
Даже после преобразования '25' → 25, поле будет удалено
из результата.
Механизмы strip и keep активно используются
в:
Их грамотное применение позволяет контролировать форму данных без дополнительной ручной фильтрации.