Joi 验证器条件模式
Joi validator conditional schema
我需要创建动态模式以根据请求查询中的键使用 Joi validator 验证我在 node js
中的 api 请求查询。说下面提到的模式是我的有效查询。
我正在使用 hapi/joi
版本 16.1.8
组合1
{ type: 1, firstname: 'user first name', lastname: 'user last name'}
组合2
{ type: 2 , salary: 1000, pension: 200}
组合3
{ type: 3 , credit: 550, debit: 100}
如您所见,对象键因 type
的值而异。如何妥善处理?
我们可以使用 Joi.alternatives like
来处理两种情况
const schema = Joi.alternatives().conditional(Joi.object({ type: 1 }).unknown(), {
then: Joi.object({
type: Joi.string(),
firstname: Joi.string(),
lastname: Joi.string()
}),
otherwise: Joi.object({
type: Joi.number(),
salary: Joi.any(),
pension: Joi.any()
})
});
但是如何在 3 个条件下做到这一点?
在 documentation 中,switch
似乎是与 alternatives.conditional
一起使用的有效密钥。您可以尝试以下方法吗?
const schema = Joi.alternatives().conditional(Joi.object({
type: 1
}).unknown(), {
switch: [{
is: 1,
then: Joi.object({
type: Joi.string(),
firstname: Joi.string(),
lastname: Joi.string(),
}),
}, {
is: 2,
then: Joi.object({
type: Joi.number(),
salary: Joi.any(),
pension: Joi.any(),
}),
}, {
// ...
}],
});
编辑 :
无法在任何地方找到有关使用 switch
关键字的任何示例...
中找到了其他实现方法
const schema = Joi.object({
a: Joi.number().required(),
b: Joi.alternatives()
.conditional('a', [
{ is: 0, then: Joi.valid(1) },
{ is: 1, then: Joi.valid(2) },
{ is: 2, then: Joi.valid(3), otherwise: Joi.valid(4) }
])
});
我以稍微不同的方式实现了同样的效果。在这里发布相同的内容,因为这可能对将来的某人有用。
const schema = Joi.object({
type: Joi.number().required().valid(1, 2, 3),
firstname: Joi.alternatives().conditional('type', { is: 1, then: Joi.string().required() }),
lastname: Joi.alternatives().conditional('type', { is: 1, then: Joi.string().required() }),
salary: Joi.alternatives().conditional('type', { is: 2, then: Joi.number().required() }),
pension: Joi.alternatives().conditional('type', { is: 2, then: Joi.number().required() }),
credit: Joi.alternatives().conditional('type', { is: 3, then: Joi.number().required() }),
debit: Joi.alternatives().conditional('type', { is: 3, then: Joi.number().required() }),
}))
正如预期的那样完美运行。
当类型值为 1
时,对象应该只有 type
、firstname
和 lastname
当类型值为 2
时,对象应该只有 type
、salary
和 pension
当类型值为 3
时,对象应该只有 type
、credit
和 debit
任何其他组合都将从 joi 验证器中间件层作为错误抛出。此外,除 1、2 和 3 之外的任何其他类型值都会引发错误。
对我有用!
var Joi = require('joi');
var schema = {
a: Joi.any().when('b', { is: 5, then: Joi.required(), otherwise: Joi.optional() }),
b: Joi.any()
};
var thing = {
b: 5
};
var validate = Joi.validate(thing, schema);
// returns
{
error: null,
value: {
b: 5
}
}
这是reference。
我试图找到一种方法来做类似的事情。然后我就想通了。
const Joi = require('joi');
const schema = Joi.object({
type: Joi.number().valid(1,2,3),
// anything common
}).when(Joi.object({type: Joi.number().valid(1)}).unknown(), {
then: Joi.object({
firstname: Joi.string(),
lastname: Joi.string(),
})
})
.when(Joi.object({type: Joi.number().valid(2)}).unknown(), {
then: Joi.object({
salary: Joi.number(),
pension: Joi.number(),
})
})
.when(Joi.object({type: Joi.number().valid(3)}).unknown(), {
then: Joi.object({
credit: Joi.number(),
debit: Joi.number(),
})
});
我想做同样的事情,但条件应该取决于请求方法而不是查询参数。我最终得到了下一个解决方案:
const schema = Joi.when(Joi.ref("$requestMethod"), {
switch: [
{
is: "POST",
then: Joi.object({
name: Joi.string().trim().max(150).required(),
description: Joi.string().max(255),
active: Joi.boolean().required(),
}),
}),
},
{
is: "PUT",
then: Joi.object({
name: Joi.string().trim().max(150).required(),
description: Joi.string().max(255),
}),
},
],
});
schema.validate(req.body, { context: { requestMethod: req.method } });
Joi when() 条件文档 https://joi.dev/api/?v=17.4.1#anywhencondition-options
使用conditional/switch,语法也更具可读性
以下 Joi 摘录将在 $.type === Type.REFERENCE
时强制出现 $.referenceClass
。当它这样做时,它将确保值是可接受的值 - ...classIds
.
否则 ($.type !== Type.REFERENCE
),它不会允许 $.referenceClass
的存在(除非你 运行 使用允许额外键的选项进行验证)。
{
type: Joi.string().valid( ...Hub.types ).required(),
referenceClass: Joi.alternatives().conditional( 'type', {
switch: [
{ is: Type.REFERENCE, then: Joi.string().valid( ...classIds ) },
],
} ),
}
我需要创建动态模式以根据请求查询中的键使用 Joi validator 验证我在 node js
中的 api 请求查询。说下面提到的模式是我的有效查询。
我正在使用 hapi/joi
版本 16.1.8
组合1
{ type: 1, firstname: 'user first name', lastname: 'user last name'}
组合2
{ type: 2 , salary: 1000, pension: 200}
组合3
{ type: 3 , credit: 550, debit: 100}
如您所见,对象键因 type
的值而异。如何妥善处理?
我们可以使用 Joi.alternatives like
来处理两种情况const schema = Joi.alternatives().conditional(Joi.object({ type: 1 }).unknown(), {
then: Joi.object({
type: Joi.string(),
firstname: Joi.string(),
lastname: Joi.string()
}),
otherwise: Joi.object({
type: Joi.number(),
salary: Joi.any(),
pension: Joi.any()
})
});
但是如何在 3 个条件下做到这一点?
在 documentation 中,switch
似乎是与 alternatives.conditional
一起使用的有效密钥。您可以尝试以下方法吗?
const schema = Joi.alternatives().conditional(Joi.object({
type: 1
}).unknown(), {
switch: [{
is: 1,
then: Joi.object({
type: Joi.string(),
firstname: Joi.string(),
lastname: Joi.string(),
}),
}, {
is: 2,
then: Joi.object({
type: Joi.number(),
salary: Joi.any(),
pension: Joi.any(),
}),
}, {
// ...
}],
});
编辑 :
无法在任何地方找到有关使用 switch
关键字的任何示例...
const schema = Joi.object({
a: Joi.number().required(),
b: Joi.alternatives()
.conditional('a', [
{ is: 0, then: Joi.valid(1) },
{ is: 1, then: Joi.valid(2) },
{ is: 2, then: Joi.valid(3), otherwise: Joi.valid(4) }
])
});
我以稍微不同的方式实现了同样的效果。在这里发布相同的内容,因为这可能对将来的某人有用。
const schema = Joi.object({
type: Joi.number().required().valid(1, 2, 3),
firstname: Joi.alternatives().conditional('type', { is: 1, then: Joi.string().required() }),
lastname: Joi.alternatives().conditional('type', { is: 1, then: Joi.string().required() }),
salary: Joi.alternatives().conditional('type', { is: 2, then: Joi.number().required() }),
pension: Joi.alternatives().conditional('type', { is: 2, then: Joi.number().required() }),
credit: Joi.alternatives().conditional('type', { is: 3, then: Joi.number().required() }),
debit: Joi.alternatives().conditional('type', { is: 3, then: Joi.number().required() }),
}))
正如预期的那样完美运行。
当类型值为 1
时,对象应该只有 type
、firstname
和 lastname
当类型值为 2
时,对象应该只有 type
、salary
和 pension
当类型值为 3
时,对象应该只有 type
、credit
和 debit
任何其他组合都将从 joi 验证器中间件层作为错误抛出。此外,除 1、2 和 3 之外的任何其他类型值都会引发错误。
对我有用!
var Joi = require('joi');
var schema = {
a: Joi.any().when('b', { is: 5, then: Joi.required(), otherwise: Joi.optional() }),
b: Joi.any()
};
var thing = {
b: 5
};
var validate = Joi.validate(thing, schema);
// returns
{
error: null,
value: {
b: 5
}
}
这是reference。
我试图找到一种方法来做类似的事情。然后我就想通了。
const Joi = require('joi');
const schema = Joi.object({
type: Joi.number().valid(1,2,3),
// anything common
}).when(Joi.object({type: Joi.number().valid(1)}).unknown(), {
then: Joi.object({
firstname: Joi.string(),
lastname: Joi.string(),
})
})
.when(Joi.object({type: Joi.number().valid(2)}).unknown(), {
then: Joi.object({
salary: Joi.number(),
pension: Joi.number(),
})
})
.when(Joi.object({type: Joi.number().valid(3)}).unknown(), {
then: Joi.object({
credit: Joi.number(),
debit: Joi.number(),
})
});
我想做同样的事情,但条件应该取决于请求方法而不是查询参数。我最终得到了下一个解决方案:
const schema = Joi.when(Joi.ref("$requestMethod"), {
switch: [
{
is: "POST",
then: Joi.object({
name: Joi.string().trim().max(150).required(),
description: Joi.string().max(255),
active: Joi.boolean().required(),
}),
}),
},
{
is: "PUT",
then: Joi.object({
name: Joi.string().trim().max(150).required(),
description: Joi.string().max(255),
}),
},
],
});
schema.validate(req.body, { context: { requestMethod: req.method } });
Joi when() 条件文档 https://joi.dev/api/?v=17.4.1#anywhencondition-options
使用conditional/switch,语法也更具可读性
以下 Joi 摘录将在 $.type === Type.REFERENCE
时强制出现 $.referenceClass
。当它这样做时,它将确保值是可接受的值 - ...classIds
.
否则 ($.type !== Type.REFERENCE
),它不会允许 $.referenceClass
的存在(除非你 运行 使用允许额外键的选项进行验证)。
{
type: Joi.string().valid( ...Hub.types ).required(),
referenceClass: Joi.alternatives().conditional( 'type', {
switch: [
{ is: Type.REFERENCE, then: Joi.string().valid( ...classIds ) },
],
} ),
}