[英]Joi - multiple `when` clauses
I have two validations to perform on the same payload:我有两个验证要对同一个有效负载执行:
When hasSalary
is true, either monthlySalary
or annualSalary
must be present.当
hasSalary
为真时,必须存在monthlySalary
或annualSalary
。
When hasCosts
is true, either monthlyCosts
or annualCosts
must be present.当
hasCosts
为真时,必须存在monthlyCosts
或annualCosts
。
I have coded this as:我已将其编码为:
Joi.object({
hasSalary: Joi.boolean(),
monthlySalary: Joi.number(),
annualSalary: Joi.number(),
hasCosts: Joi.boolean(),
monthlyCosts: Joi.number(),
annualCosts: Joi.number(),
})
.when(
Joi.object({ hasSalary: Joi.boolean().valid(true).required() }),
{
then: Joi.object().xor('monthlySalary', 'annualSalary')
}
)
.when(
Joi.object({ hasCosts: Joi.boolean().valid(true).required() }),
{
then: Joi.object().xor('monthlyCosts', 'annualCosts')
}
);
This correctly gives a validation error for: { hasSalary: true }
:这正确地给出了验证错误:
{ hasSalary: true }
:
message: '"value" must contain at least one of [monthlySalary, annualSalary]'
... and for { hasCosts: true }
: ...对于
{ hasCosts: true }
:
message: '"value" must contain at least one of [monthlyCosts, annualCosts]'
... but doesn't work as I expected when both the booleans are true
, and the second when
's constraints are not met: ...但是当两个布尔值都为
true
并且第二个when
的约束不满足when
,它不会像我预期的那样工作:
{
hasSalary: true,
monthlySalary: 300,
hasCosts: true,
}
I hoped for "value" must contain at least one of [monthlyCosts, annualCosts]
here, but instead I got a clean validation with no error.我希望这里的
"value" must contain at least one of [monthlyCosts, annualCosts]
,但我得到了一个没有错误的干净验证。
I think I understand what's happening - chaining when
s is creating a series of guards, and the first matching one wins.我想我明白发生了什么 -
when
s 创建一系列守卫when
链接when
第一个匹配的人获胜。
So what construct can I use in Joi (ideally version 15) to achieve what I wanted?那么我可以在 Joi(最好是 15 版)中使用什么构造来实现我想要的?
With the newest version Joi
17.2.1 you don't have this problem (multiple when conditions resolve correctly)使用最新版本的
Joi
17.2.1,您不会遇到此问题(条件正确解决时会出现多个)
But with Joi
15.1.1 you can use the following workaround:但是对于
Joi
15.1.1,您可以使用以下解决方法:
const Joi = require('@hapi/joi');
const one = Joi.object({
hasSalary: Joi.boolean().valid(true),
monthlySalary: Joi.number(),
annualSalary: Joi.number(),
}).xor('monthlySalary', 'annualSalary');
const two = Joi.object({
hasSalary: Joi.boolean().valid(false),
monthlySalary: Joi.number(),
annualSalary: Joi.number(),
});
const three = Joi.object({
hasCosts: Joi.boolean().valid(true),
monthlyCosts: Joi.number(),
annualCosts: Joi.number(),
}).xor('monthlyCosts', 'annualCosts');
const four = Joi.object({
hasCosts: Joi.boolean().valid(false),
monthlyCosts: Joi.number(),
annualCosts: Joi.number(),
});
const one_three = one.concat(three);
const one_four = one.concat(four);
const two_three = two.concat(three);
const two_four = two.concat(four);
const schema = Joi.alternatives().try(
one,
two,
three,
four,
one_three,
one_four,
two_three,
two_four,
);
Run some tests:运行一些测试:
// works
const data1 = {
hasSalary: true,
monthlySalary: 2000,
};
console.log(schema.validate(data1).error);
// works
const data2 = {
hasSalary: false,
};
console.log(schema.validate(data2).error);
// works
const data3 = {
hasCosts: true,
monthlyCosts: 300,
};
console.log(schema.validate(data3).error);
// works
const data4 = {
hasCosts: false,
};
console.log(schema.validate(data4).error);
// works
const data5 = {
hasSalary: true,
monthlySalary: 2000,
hasCosts: true,
monthlyCosts: 300,
};
console.log(schema.validate(data5).error);
// works
const data6 = {
hasSalary: false,
hasCosts: true,
monthlyCosts: 300,
};
console.log(schema.validate(data6).error);
// works
const data7 = {
hasSalary: true,
monthlySalary: 2000,
hasCosts: false,
};
console.log(schema.validate(data7).error);
// works
const data8 = {
hasSalary: false,
hasCosts: false,
};
console.log(schema.validate(data8).error);
// error
const data9 = {
hasSalary: true
};
console.log(schema.validate(data9).error.message)
// error
const data10 = {
hasSalary: true,
annualSalary: 1000,
hasCosts: true,
};
console.log(schema.validate(data10).error.message)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.