简体   繁体   English

Joi - 多个 `when` 子句

[英]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为真时,必须存在monthlySalaryannualSalary

When hasCosts is true, either monthlyCosts or annualCosts must be present.hasCosts为真时,必须存在monthlyCostsannualCosts

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM