我有这个Joi模式:
let schema = {};
let stations = {
contact: {
first_name: Joi.string().min(2).max(10).regex(Regex.alphabeta, 'alphabeta').allow("").error(JoiCustomErrors),
last_name: Joi.string().min(2).max(10).regex(Regex.alphabeta, 'alphabeta').allow("").error(JoiCustomErrors),
phone: Joi.string().min(10).max(10).regex(Regex.num, 'num').allow("").error(JoiCustomErrors),
},
address: {
place: Joi.string().min(2).max(10).regex(Regex.alphanum, 'alphanum').required().error(JoiCustomErrors),
city: Joi.string().min(2).max(30).required().error(JoiCustomErrors),
street: Joi.string().min(2).max(30).regex(Regex.alphabeta, 'alphabeta').required().error(JoiCustomErrors),
house_number: Joi.string().min(1).max(6).regex(Regex.alphanum, 'alphanum').allow("").error(JoiCustomErrors)
},
passengers_amount: Joi.number().min(0).max(4).required().error(JoiCustomErrors),
notes: Joi.string().min(2).max(100).regex(Regex.alphanum, 'alphanum').allow("").error(JoiCustomErrors)
};
schema.stations = Joi.array().items(stations).min(1).max(5).required().error(JoiCustomErrors);
如您所见,schema.stations
是最小1个元素和最大5个元素的数组。
我希望只有在"contact.first_name" AND "contact.last_name" AND "contact.phone"
存在(或根据架构正确填充)的情况下,每个元素才具有“ address.place”字段。
我该怎么做?
答案 0 :(得分:1)
您可以使用Joi.when()
并创建如下所示的模式:
Joi.object().keys({
contact: Joi.object().keys({
first_name: Joi.string(),
last_name: Joi.string(),
phone: Joi.string(),
}),
address: Joi.object().keys({
place: Joi.string(),
city: Joi.string().min(2).max(30),
street: Joi.string(),
house_number: Joi.string()
}).when('contact', {
is: Joi.object().keys({
first_name: Joi.exist(),
last_name: Joi.exist(),
phone: Joi.exist(),
}),
then: Joi.object({ place: Joi.required() }).required(),
otherwise: Joi.object({ place: Joi.forbidden() })
}),
passengers_amount: Joi.number(),
notes: Joi.string()
});
我只是简化了您的shema,所以很容易理解。
基本上,我们在这里所说的是,如果 concat.first_name , concat.last_name 和 concat.phone 存在 < / em>,则地址和 address.place 是必需的,否则 address.place 是禁止的。
例如,此对象将失败,因为地址不存在:
{
address: {
first_name: 'a',
last_name: 'b',
phone: 'c'
}
}
,这将失败,因为 address.place 不存在:
{
address: {
first_name: 'a',
last_name: 'b',
phone: 'c'
},
concact: {
}
}
最后,根据定义的架构,该对象将通过:
{
address: {
first_name: 'a',
last_name: 'b',
phone: 'c'
},
concact: {
place: 'd'
}
};
答案 1 :(得分:0)
感谢Soltex,这就是应该使用的正确模式(但是请参考我所做的更改):
Joi.object().keys({
contact: {
first_name: Joi.string().min(2).max(10).regex(Regex.alphabeta, 'alphabeta').allow("").error(JoiCustomErrors),
last_name: Joi.string().min(2).max(10).regex(Regex.alphabeta, 'alphabeta').allow("").error(JoiCustomErrors),
phone: Joi.string().min(10).max(10).regex(Regex.num, 'num').allow("").error(JoiCustomErrors),
},
address: Joi.object().keys({
place: Joi.string().min(2).max(10).regex(Regex.alphanum, 'alphanum').error(JoiCustomErrors),
city: Joi.string().min(2).max(30).required().error(JoiCustomErrors),
street: Joi.string().min(2).max(30).regex(Regex.alphabeta, 'alphabeta').required().error(JoiCustomErrors),
house_number: Joi.string().min(1).max(6).regex(Regex.alphanum, 'alphanum').allow("").error(JoiCustomErrors)
}).when('contact', {
is: Joi.object().keys({
first_name: Joi.string().min(1),
last_name: Joi.string().min(1),
phone: Joi.string().min(1),
}),
then: Joi.object({ place: Joi.required() }).required(),
otherwise: Joi.object({
place: Joi.optional().allow("")
})
}),
passengers_amount: Joi.number().min(0).max(4).required().error(JoiCustomErrors),
notes: Joi.string().min(2).max(100).regex(Regex.alphanum, 'alphanum').allow("").error(JoiCustomErrors)
})
请注意,从我的答案更改为Soltex的答案: 他将“ contact.first_name”“ contact.last_name”“ contact.phone” 设置为: Joi.exists() 。这不好,因为以这种方式甚至“存在”一个空对象,然后要求用户提供“ address.place”。我们不需要这样的东西,我们需要在每个字段中至少保留一个字符。
此外,Soltex答案中的else语句使用的是 Joi.forbidden(),尽管这不是此处的预期行为-我们仍然需要允许用户提供位置,即使没有联系人,但这不是必须的-因此,我改用了: Joi.optional() 。