[英]Joi validator conditional schema
I need to create dynamic schema to validate my api request query in node js
using Joi validator depending on a key in the request query.我需要创建动态模式以根据请求查询中的键使用Joi 验证器在
node js
验证我的 api 请求查询。 Say the following below mentioned pattern are my valid queries.说下面提到的模式是我的有效查询。
I'm using hapi/joi
version 16.1.8
我正在使用
hapi/joi
16.1.8
版本16.1.8
Combination 1组合1
{ type: 1, firstname: 'user first name', lastname: 'user last name'}
Combination 2组合2
{ type: 2 , salary: 1000, pension: 200}
Combination 3组合3
{ type: 3 , credit: 550, debit: 100}
As you can see the object keys varies depending on the value of type
.如您所见,对象键因
type
的值而异。 How this can be handled properly?如何正确处理?
We can handle two conditions using Joi.alternatives like我们可以使用Joi.alternatives处理两个条件,例如
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()
})
});
But how this can be done for 3 conditions?但是如何在 3 个条件下做到这一点?
I achieved the same in a little different manner.我以稍微不同的方式实现了相同的目标。 Posting the same here since this might be useful for someone in future.
在这里发布相同的内容,因为这可能对将来的某人有用。
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() }),
}))
This was working perfectly as expected.这正如预期的那样完美地工作。
When the type value is 1
the object should have only type
, firstname
and lastname
当类型值为
1
,对象应该只有type
、 firstname
和lastname
When the type value is 2
the object should have only type
, salary
and pension
当类型值为
2
,对象应该只有type
、 salary
和pension
When the type value is 3
the object should have only type
, credit
and debit
当 type 值为
3
,对象应该只有type
、 credit
和debit
Any other combination will be thrown as error from the joi validator middleware layer.任何其他组合都将从 joi 验证器中间件层作为错误抛出。 Also any other type value other that 1, 2 and 3 will be throwing error.
此外,除 1、2 和 3 之外的任何其他类型值都将引发错误。
It works for me!这个对我有用!
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
}
}
In the documentation it look like switch
is valid key to use along alternatives.conditional
.在文档中,看起来
switch
是与alternatives.conditional
一起使用的有效键。 Could you try the following ?您可以尝试以下方法吗?
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(),
}),
}, {
// ...
}],
});
EDIT :编辑:
Couldn't find any example anywhere about the use of the switch
keyword...在任何地方都找不到有关使用
switch
关键字的任何示例...
But found some other way to achieve it in hapijs/joi github但是在hapijs/joi github 中找到了一些其他方法来实现它
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) }
])
});
I was trying to find a way to do something similar.我试图找到一种方法来做类似的事情。 Then I was able to figure it out.
然后我就想通了。
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(),
})
});
I was looking to do the same but instead of query param the condition should depend on the request method.我想做同样的事情,但条件应该取决于请求方法而不是查询参数。 I ended up with the next solution:
我最终得到了下一个解决方案:
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() condition documentation https://joi.dev/api/?v=17.4.1#anywhencondition-options Joi when() 条件文档https://joi.dev/api/?v=17.4.1#anywhencondition-options
Using the conditional/switch, of which syntax is also more readable.使用条件/开关,其语法也更具可读性。
The following Joi excerpt will enforce the presence of $.referenceClass
when $.type === Type.REFERENCE
.以下 Joi 摘录将在
$.type === Type.REFERENCE
时强制$.referenceClass
的存在。 When it does, it will ensure that values are the accepted ones - ...classIds
.当它这样做时,它将确保值是接受的值 -
...classIds
。
Otherwise ( $.type !== Type.REFERENCE
), it won't allow the presence of $.referenceClass
(except you run the validation with the option of allowing extra keys).否则(
$.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 ) },
],
} ),
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.