Joi 验证器条件模式

Nit*_*esh 11 javascript node.js hapijs joi

我需要创建动态模式以根据请求查询中的键node js使用Joi 验证器来验证我的 api请求查询。说下面提到的模式是我的有效查询。

我正在使用hapi/joi版本16.1.8

组合1

{ type: 1, firstname: 'user first name', lastname: 'user last name'}
Run Code Online (Sandbox Code Playgroud)

组合2

{ type: 2 , salary: 1000, pension: 200}
Run Code Online (Sandbox Code Playgroud)

组合3

{ type: 3 , credit: 550, debit: 100}
Run Code Online (Sandbox Code Playgroud)

如您所见,对象键因 的值而异type。如何正确处理?

我们可以使用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()
    })
});
Run Code Online (Sandbox Code Playgroud)

但是如何在 3 个条件下做到这一点?

Nit*_*esh 12

我以稍微不同的方式实现了相同的目标。在这里发布相同的内容,因为这可能对将来的某人有用。

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() }),
}))
Run Code Online (Sandbox Code Playgroud)

这正如预期的那样完美地工作。

当类型值为1对象时,应该只有typefirstname并且lastname

当类型值为2对象时,应该只有typesalary并且pension

当类型值为3对象时,应该只有typecredit并且debit

任何其他组合都将从 joi 验证器中间件层作为错误抛出。此外,除 1、2 和 3 之外的任何其他类型值都将引发错误。

  • 编写条件语句时要小心。还有`any().when()`,区别很微妙。/sf/ask/5180266451/ Between-alternatives-conditional-and-any-when (2认同)

小智 9

我试图找到一种方法来做类似的事情。然后我就明白了。

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(),
  })
});

Run Code Online (Sandbox Code Playgroud)


Gré*_*EUT 8

文档中,它看起来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(),
    }),
  }, {
    // ...
  }],
});
Run Code Online (Sandbox Code Playgroud)

编辑

无法在任何地方找到有关使用关键字的任何示例switch...

但在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) }
    ])
});
Run Code Online (Sandbox Code Playgroud)


soa*_*ing 6

这个对我有用!

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
    }
}
Run Code Online (Sandbox Code Playgroud)

这是参考