使用 Joi,要求两个字段之一不为空

Posted

技术标签:

【中文标题】使用 Joi,要求两个字段之一不为空【英文标题】:Using Joi, require one of two fields to be non empty 【发布时间】:2015-05-06 01:15:49 【问题描述】:

如果我有两个字段,我只想验证至少一个字段何时为非空字符串,但当两个字段均为空字符串时验证失败。

类似这样的东西无法验证

var schema = Joi.object().keys(
    a: Joi.string(),
    b: Joi.string()
).or('a', 'b');

验证时

a: 'aa', b: ''

or 条件仅测试是否存在键 ab,但会测试 ab 的条件是否为真。 Joi.string() 将因空字符串而失败。

这里有一些测试用例来演示的要点

http://requirebin.com/?gist=84c49d8b81025ce68cfb

【问题讨论】:

【参考方案1】:

下面的代码对我有用。我使用了替代方案,因为 .or 确实在测试密钥的存在,而您真正想要的是允许一个或另一个为空的替代方案。

var console = require("consoleit");
var Joi = require('joi');

var schema = Joi.alternatives().try(
  Joi.object().keys(
    a: Joi.string().allow(''),
    b: Joi.string()
    ),
  Joi.object().keys(
    a: Joi.string(),
    b: Joi.string().allow('')
    )
);

var tests = [
  // both empty - should fail
  a: '', b: '',
  // one not empty - should pass but is FAILING
  a: 'aa', b: '',
  // both not empty - should pass
  a: 'aa', b: 'bb',
  // one not empty, other key missing - should pass
  a: 'aa'
];

for(var i = 0; i < tests.length; i++) 
  console.log(i, Joi.validate(tests[i], schema)['error']);

【讨论】:

这确实有效,但不是真正可扩展的——如果你有两组,你需要四个替代方案,如果你有三组,那么你需要八个。不过似乎没有更好的方法。 太棒了。谢谢【参考方案2】:

另一种使用 Joi.when() 的方法对我有用:

var schema = Joi.object().keys(
  a: Joi.string().allow(''),
  b: Joi.when('a',  is: '', then: Joi.string(), otherwise: Joi.string().allow('') )
).or('a', 'b')

.or('a', 'b') 防止 a AND b 为空(而不是 '')。

【讨论】:

我刚刚意识到这将返回消息 "b" is required 而不是 either "a" or "b" is required 但不知道如何解决。【参考方案3】:

如果您想表达两个字段之间的依赖关系,而不必重复对象的所有其他部分,您可以使用when:

var schema = Joi.object().keys(
  a: Joi.string().allow(''),
  b: Joi.string().allow('').when('a',  is: '', then: Joi.string() )
).or('a', 'b');

【讨论】:

【参考方案4】:

我遇到https://***.com/a/61212051/15265372 答案的问题是,如果两个字段都给出,你不会遇到任何错误,如果你想解决这个问题,你需要用xor 替换or

【讨论】:

以上是关于使用 Joi,要求两个字段之一不为空的主要内容,如果未能解决你的问题,请参考以下文章

是否可以从一组定义的字段中要求至少一个字段?

EF 核心 6 选择空值,尽管 where 子句要求不为空

在查询SQL语句中为空或不为空怎么写

在查询SQL语句中为空或者不为空的字段应该怎么写?

获取两个字段中不为空的那个字段 ---SQL

Oracle中查询某字段不为空的SQL语句怎么写