【发布时间】:2019-10-08 14:57:45
【问题描述】:
我需要使用joi 验证架构。
对象是这样的:
- 有一个名为“type”的必需属性,其值可以是
TYPE1、TYPE2、TYPE3。 - 如果
type === 'TYPE1',我们必须期望属性one、two和three在同一级别。 - 如果
type === 'TYPE2',我们必须期望属性four、five和six处于同一级别。 - 如果
type === 'TYPE3',我们必须期望subtype属性在同一级别,可能的值A和B。- 如果
subtype === 'A',那么我们必须期望属性seven、eight、nine处于同一级别。 - 如果
subtype === 'B',那么我们必须期望属性ten、eleven、twelve处于同一级别。
- 如果
这是我想出的:
import { object, string, validate } from 'joi';
const obj1 = { // valid
type: 'TYPE1',
one: '01',
two: '02',
three: '03',
};
const obj2 = { // valid
type: 'TYPE2',
four: '04',
five: '05',
six: '06',
};
const obj3 = { // valid
type: 'TYPE3',
subtype: 'A',
seven: '07',
eight: '08',
nine: '09',
};
const obj4 = { // valid
type: 'TYPE3',
subtype: 'B',
ten: '10',
eleven: '11',
twelve: '12',
};
const joiSchema = object({
// point 1
type: string().valid('TYPE1', 'TYPE2', 'TYPE3').required(),
})
.when(
// point 2
object({ type: 'TYPE1' }).unknown(),
{
then: object({
one: string().required(),
two: string().required(),
three: string().required(),
}),
},
)
.when(
// point 3
object({ type: 'TYPE2' }).unknown(),
{
then: object({
four: string().required(),
five: string().required(),
six: string().required(),
}),
},
)
.when(
// point 4
object({ type: 'TYPE3' }).unknown(),
{
then: object(
// if type === 'TYPE3', check for one of those schemas
{
// point 4
subtype: string().valid('A', 'B'),
},
).when(
// point 4.1
object({ subtype: 'A' }).unknown(),
{
then: object({
seven: string().required(),
eight: string().required(),
nine: string().required(),
}),
},
).when(
// point 4.2
object({ subtype: 'B' }).unknown(),
{
then: object({
ten: string().required(),
eleven: string().required(),
twelve: string().required(),
}),
},
),
},
);
const result1 = validate(obj1, joiSchema);
console.log('Validating obj1')
if (result1.error) {
console.error(result1.error.message);
}
const result2 = validate(obj2, joiSchema);
console.log('Validating obj2')
if (result2.error) {
console.error(result2.error.message);
}
const result3 = validate(obj3, joiSchema);
console.log('Validating obj3')
if (result3.error) {
console.error(result3.error.message);
}
const result4 = validate(obj4, joiSchema);
console.log('Validating obj4')
if (result4.error) {
console.error(result4.error.message);
}
此 sn-p 可在此处进行测试:https://repl.it/@AlessandroDe5/Joi-MCVE
显示这个错误:
AssertionError [ERR_ASSERTION]: Cannot merge type object with another type: alternatives
at new AssertionError (internal/errors.js:315:11)
at Object.exports.assert (/home/runner/node_modules/hoek/lib/index.js:559:11)
at internals.Object.concat (/home/runner/node_modules/joi/lib/types/any/index.js:148:14)
at internals.Alternatives.when (/home/runner/node_modules/joi/lib/types/alternatives/index.js:131:52)
at index.ts:52:6
at Script.runInThisContext (vm.js:65:33)
at startRepl (/usr/local/lib/node_modules/ts-node-fm/src/bin.ts:157:12)
at Object.<anonymous> (/usr/local/lib/node_modules/ts-node-fm/src/bin.ts:66:1)
at Module._compile (internal/modules/cjs/loader.js:654:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:665:10)
如果我删除嵌套的 when(第 4、4.1、4.2 点),它可以正常工作,并且当然会拒绝最后两个对象。
我还尝试将when 替换为alternatives:
.when(
// point 4
object({ type: 'TYPE3' }).unknown(),
{
then: alternatives().try(
object({
subtype: string().valid('A'),
seven: string().required(),
eight: string().required(),
nine: string().required(),
}),
).when(
object({
subtype: string().valid('B'),
ten: string().required(),
eleven: string().required(),
twelve: string().required(),
}),
),
},
);
正如人们所料,我得到了完全相同的错误。
有没有办法以某种方式完成任务?
【问题讨论】:
-
你检查过这个 github 问题了吗? github.com/hapijs/joi/issues/1021 听起来和你的问题很相似。不过,在第 52 行抛出了错误,这很奇怪。
-
@briosheje 是的,我看过那个问题,不幸的是他们说要使用
when/is/then/otherwise,这是有限制的,因为我只能有两个分支(then,otherwise)。我的 MCVE 被简化了,我的真实场景是大约 10 种不同的模式,它们基于subtype而不同,所以我不能在这里使用这个解决方案。也许我可以链接when/otherwise来重现if/else if场景,但这看起来很难看。这是唯一的解决方案吗? -
不确定,我个人以前从未使用过 joi。也许其他人有其他想法。否则,您可能想打开另一个问题或重新打开现有问题,也许作者或团队可能会给您进一步的帮助
标签: javascript typescript joi