简体   繁体   中英

How to use references (object values) at validation point in Joi?

I am trying to conditionally validate a key key1 based on the value of different key key2 . The key1 is from some set of values, lets say ['a', 'b', 'c'] and key2 should be also constrained depending on the value of key1 {a: ['a1','a2','a3'], b: ['b1','b2','b3'], c: ['c1','c2','c3'] } .

If key1 is a then key2 has to be one of ['a1','a2','a3'] etc. The set of values of key2 is not computable from key1 .

I tried following schemas, using ref, hoping joi.ref('key1') , just gets me the value:

const obj = {a: ['a1','a2','a3'], b: ['b1','b2','b3'], c: ['c1','c2','c3'] }
const schema = {
  key1: joi.only(['a', 'b', 'c']),
  key2: joi.only(obj[joi.ref('key1')])
}

and I get the error:

"Cannot call allow/valid/invalid with undefined"

I've tried it with options map specified:

const schema = {
  key1: joi.only(['a', 'b', 'c']),
  key2: joi.only(joi.ref('key1', {map: [['a', ['a1','a2','a3']],['b', ['b1','b2','b3']],['c', ['c1','c2','c3']]]}))
}

For {key1:'a', key2:'a1'} I get ValidationError:

"child "key2" fails because ["key2" must be one of [ref:key1]]

But curiously {key1:'a', key2:'a'} gets validated without error, which suggests the fallback of joi.ref to the original value.

So refs did not work as expected lets try when and switch:

const schema = {
key1: joi.only(['a', 'b', 'c']),
key2: joi.when('key1', {switch: [{is: 'a', then: joi.only(['a1','a2','a3'])},{is: 'b', then: joi.only(['b1','b2','b3'])},{is: 'c', then: joi.only(['c1','c2','c3'])}]})
}

But this gets me only:

"options must have at least one of 'then' or 'otherwise'"

And if I supply otherwise , it also requires is . Is there any simple way how to tackle this problem?

I suggest you to try two different approaches in order to solve your problem.

The first one uses multiple Joi.when() conditions:

const schema = joi.object({
    key1: joi.array().items(joi.string().valid('a','b','c')).unique(),
    key2: joi.array()
        .when('key1', { is: ['a'], then: joi.array().items(joi.string().valid('a1','a2','a3')).unique(), otherwise: joi.forbidden() })
        .when('key1', { is: ['b'], then: joi.array().items(joi.string().valid('b1','b2','b3')).unique(), otherwise: joi.forbidden() })
        .when('key1', { is: ['c'], then: joi.array().items(joi.string().valid('c1','c2','c3')).unique(), otherwise: joi.forbidden() })
})

The second one uses the Joi.alternatives() :

const schema = joi.alternatives().try(
joi.object({
    key1: joi.array().items(joi.string().valid('a')).unique().required(),
    key2: joi.array().items(joi.string().valid('a1','a2','a3')).unique().required()
}),
joi.object({
    key1: joi.array().items(joi.string().valid('b')).unique().required(),
    key2: joi.array().items(joi.string().valid('b1','b2','b3')).unique().required()
}),
joi.object({
    key1: joi.array().items(joi.string().valid('c')).unique().required(),
    key2: joi.array().items(joi.string().valid('c1','c2','c3')).unique().required()
}))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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