如何在 JOI 17 中添加自定义验证器?
How do I add custom validators in JOI 17?
我正在使用 JOI 14,似乎找不到升级到 17 的升级指南。我看到有人针对 JOI 16 发布了类似的问题,但最后一次更新是在 3 个月前。根据我在 .
中看到的情况,在 16 年似乎不需要 type
我正在查看 https://joi.dev/api/?v=17.3.0#extensions 而 type
的描述是 The type of schema. Can be a string, or a regular expression that matches multiple types.
。
我试过这样的事情:
const snakeAlpha = joi => {
return {
type: 'object',
name: 'snakeAlpha',
base: joi.string().regex(/^[a-z]+(_[a-z]+)*$/)
};
};
const customJoi = Joi.extend({
type: 'object',
rules: {
snakeAlpha
}
});
它给我这个错误:
ValidationError: {
"type": "object",
"rules": {
"snakeAlpha" [1]: "[joi => {\n return {\n type: 'object',\n name: 'snakeAlpha',\n base: joi.string().regex(/^[a-z]+(_[a-z]+)*$/)\n };\n}]"
}
}
[1] "rules.snakeAlpha" must be of type object
说完object
我就糊涂了。我也尝试了 string
因为这就是基础,但它有相同的错误消息。
更新
我还意识到原始示例仅涵盖了一个未引用 joi (regex) 的简单规则。我也有引用其他自定义验证器的验证器,如下所示。破案也加分。
const arrayKebabAlpha = joi => {
return {
type: 'string',
name: 'arrayKebabAlpha',
base: joi.array().items(joi.kebabAlpha())
};
};
Joi 扩展的文档对于如此有用的功能来说乏善可陈,令人失望。幸运的是,Joi 的很多核心都是使用扩展编写的,因此可以从 the source.
中学到很多东西
如果我把你的规则写成扩展,它会是这样的:
const customJoi = Joi.extend(joi => ({
type: 'string',
base: joi.string(),
messages: {
'string.snakeAlpha': '{{#label}} must be snake case'
},
rules: {
snakeAlpha: {
validate(value, helpers)
{
if (!/^[a-z]+(_[a-z]+)*$/.test(value))
{
return helpers.error('string.snakeAlpha', { value });
}
return value;
}
}
}
}));
可以这样使用:
customJoi.object().keys({
foo: customJoi.string().snakeAlpha()
});
更新
我不确定这是否是处理依赖扩展的正确方式,但这是我通常处理它们的方式...
我首先在一个数组中定义我的扩展,确保首先定义依赖扩展。然后我将遍历数组,重新使用之前的 customJoi
实例,以便下一个扩展包含之前定义的那些。一个简单的工作示例可能会比我用文字解释得更好!
(我还简化了扩展,使其更符合您习惯使用它们的方式)
const Joi = require('joi');
let customJoi = Joi;
const extensions = [
joi => ({
type: 'snakeAlpha',
base: joi.string().regex(/^[a-z]+(_[a-z]+)*$/)
}),
// this instance of 'joi' will include 'snakeAlpha'
joi => ({
type: 'kebabAlpha',
base: joi.string().regex(/^[a-z]+(-[a-z]+)*$/)
}),
// this instance of 'joi' will include 'snakeAlpha' and 'kebabAlpha'
joi => ({
type: 'arrayKebabAlpha',
base: joi.array().items(joi.kebabAlpha())
})
];
extensions.forEach(extension =>
customJoi = customJoi.extend(extension));
customJoi.assert([ 'hello-world' ], customJoi.arrayKebabAlpha());
我正在使用 JOI 14,似乎找不到升级到 17 的升级指南。我看到有人针对 JOI 16 发布了类似的问题,但最后一次更新是在 3 个月前。根据我在
type
我正在查看 https://joi.dev/api/?v=17.3.0#extensions 而 type
的描述是 The type of schema. Can be a string, or a regular expression that matches multiple types.
。
我试过这样的事情:
const snakeAlpha = joi => {
return {
type: 'object',
name: 'snakeAlpha',
base: joi.string().regex(/^[a-z]+(_[a-z]+)*$/)
};
};
const customJoi = Joi.extend({
type: 'object',
rules: {
snakeAlpha
}
});
它给我这个错误:
ValidationError: {
"type": "object",
"rules": {
"snakeAlpha" [1]: "[joi => {\n return {\n type: 'object',\n name: 'snakeAlpha',\n base: joi.string().regex(/^[a-z]+(_[a-z]+)*$/)\n };\n}]"
}
}
[1] "rules.snakeAlpha" must be of type object
说完object
我就糊涂了。我也尝试了 string
因为这就是基础,但它有相同的错误消息。
更新 我还意识到原始示例仅涵盖了一个未引用 joi (regex) 的简单规则。我也有引用其他自定义验证器的验证器,如下所示。破案也加分。
const arrayKebabAlpha = joi => {
return {
type: 'string',
name: 'arrayKebabAlpha',
base: joi.array().items(joi.kebabAlpha())
};
};
Joi 扩展的文档对于如此有用的功能来说乏善可陈,令人失望。幸运的是,Joi 的很多核心都是使用扩展编写的,因此可以从 the source.
中学到很多东西如果我把你的规则写成扩展,它会是这样的:
const customJoi = Joi.extend(joi => ({
type: 'string',
base: joi.string(),
messages: {
'string.snakeAlpha': '{{#label}} must be snake case'
},
rules: {
snakeAlpha: {
validate(value, helpers)
{
if (!/^[a-z]+(_[a-z]+)*$/.test(value))
{
return helpers.error('string.snakeAlpha', { value });
}
return value;
}
}
}
}));
可以这样使用:
customJoi.object().keys({
foo: customJoi.string().snakeAlpha()
});
更新
我不确定这是否是处理依赖扩展的正确方式,但这是我通常处理它们的方式...
我首先在一个数组中定义我的扩展,确保首先定义依赖扩展。然后我将遍历数组,重新使用之前的 customJoi
实例,以便下一个扩展包含之前定义的那些。一个简单的工作示例可能会比我用文字解释得更好!
(我还简化了扩展,使其更符合您习惯使用它们的方式)
const Joi = require('joi');
let customJoi = Joi;
const extensions = [
joi => ({
type: 'snakeAlpha',
base: joi.string().regex(/^[a-z]+(_[a-z]+)*$/)
}),
// this instance of 'joi' will include 'snakeAlpha'
joi => ({
type: 'kebabAlpha',
base: joi.string().regex(/^[a-z]+(-[a-z]+)*$/)
}),
// this instance of 'joi' will include 'snakeAlpha' and 'kebabAlpha'
joi => ({
type: 'arrayKebabAlpha',
base: joi.array().items(joi.kebabAlpha())
})
];
extensions.forEach(extension =>
customJoi = customJoi.extend(extension));
customJoi.assert([ 'hello-world' ], customJoi.arrayKebabAlpha());