Joi: Use "when" inside "when" in Joi

Created on 2 Nov 2016  路  7Comments  路  Source: sideway/joi

Context

  • node version: 4.2.3
  • joi version: ^9.0.4
  • environment (node, browser): node
  • used with (hapi, standalone, ...): standalone
  • any other relevant information:

What are you trying to achieve or the steps to reproduce ?

I have a complex condition where I need to use "when" inside a "when". I am getting the error
"Cannot merge type boolean with another type: alternatives"

Describe your issue here, include schemas and inputs you are validating if needed.

const schema = Joi.object().keys({
a: Joi.boolean(),
b: Joi.string(),
c: AnotherJoiObject.when("a", {"is": true, "then": Joi.optional(), "otherwise": Joi.forbidden()}),
d: Joi.boolean()
});

const AnotherJoiObject = Joi.object().keys({
object1: childJoiObject1,
object2: childJoiObject2
})
.when("b", {"is": "something", "then": Joi.object({
  object1: Joi.optional().when("d",{
              "is": true,
              "then": Joi.object({
             "prop1": Joi.required()
          })
}),
 object2: Joi.forbidden()
 }),
"otherwise": Joi.object({
  object2: Joi.optional(),
 object1: Joi.forbidden()
 })
});

Which result you had ?

As can be seen, "c" is another joi object, which is dependent upon "a". And again, c.object1 and c.object2 are dependent upon "b". And "c.object1.prop1" is dependent on "d". I am getting the error "Cannot merge type boolean with another type: alternatives"

What did you expect ?

I need to get "c.object1.prop1" to be required or optional when "d" is true/false.

feature

Most helpful comment

The solution to this would be that your topmost validation should always start with Joi.when() and not AnotherJoiObject

@avparmar1805 see my example below:

// ...
// ...

'animal': Joi 
        .when('legs', {
          is: 2,
          then: Joi
            .when('species', {
              is: 'mammal', 
              then: Joi.string().valid('human').valid('kangaroo').required() 
            })
            .when('species', {
              is: 'bird', 
              then: Joi.string().valid('eagle').valid('toucan').required() 
            })
        })

// ...
// ...

This will prevent the "Cannot merge type boolean with another type: alternatives" error.

All 7 comments

what are the definitions of childJoiObject1 and childJoiObject2?

I think the errors you're getting are related to having object1 defined in object().keys() and in the alternatives definition.

This is something I looked into a while ago, I'd say it's a bug/enhancement but it'll take time. The problem is he's trying to merge an object with an alternative containing objects, in theory it should work, but the current concat algorithm doesn't deal with that. Feel free to take that one if you love hard problems.

The solution to this would be that your topmost validation should always start with Joi.when() and not AnotherJoiObject

@avparmar1805 see my example below:

// ...
// ...

'animal': Joi 
        .when('legs', {
          is: 2,
          then: Joi
            .when('species', {
              is: 'mammal', 
              then: Joi.string().valid('human').valid('kangaroo').required() 
            })
            .when('species', {
              is: 'bird', 
              then: Joi.string().valid('eagle').valid('toucan').required() 
            })
        })

// ...
// ...

This will prevent the "Cannot merge type boolean with another type: alternatives" error.

@avparmar1805

For your code, try doing this instead:

const AnotherJoiObject = Joi.object().keys({
object1: childJoiObject1,
object2: childJoiObject2
})
.when("b", {"is": "something", "then": Joi.object({
  object1: Joi.optional().when("d",{
              "is": true,
              "then": Joi.object({
             "prop1": Joi.required()
          })
}),
 object2: Joi.forbidden()
 }),
"otherwise": Joi.object({
  object2: Joi.optional(),
 object1: Joi.forbidden()
 })
});

const schema = Joi.object().keys({
a: Joi.boolean(),
b: Joi.string(),
c: Joi.when("a", {"is": true, "then": AnotherJoiObject.optional(), "otherwise": Joi.forbidden()}),
d: Joi.boolean()
});

Maybe we can mark this as resolved?

This thread has been automatically locked due to inactivity. Please open a new issue for related bugs or questions following the new issue template instructions.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Taxi4you picture Taxi4you  路  3Comments

longweiquan picture longweiquan  路  3Comments

normancarcamo picture normancarcamo  路  3Comments

farwayer picture farwayer  路  3Comments

kevbook picture kevbook  路  4Comments