Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Joi when sibling then add extra rules at root

Tags:

joi

I have a complex validation which changes depending on the a value in the JSON.

{ type: 'a', thing: 1, foo: 'abc' }
{ type: 'b', thing: 2, bar: 123 }

I want to validate that if the type is a, then use one set of siblings, if b then use another set of siblings

I would like to use the when switch, but cant work out how to do this at the root.

Joi.object({
  type: Joi.string().valid('a','b').required(),
  thing: Joi.number().required()
}).when('type', {
  switch: [
    { is: 'a', then: Joi.object({ foo: Joi.string() }) },
    { is: 'b', then: Joi.object({ bar: Joi.number() }) },
  ],
  otherwise: Joi.forbidden(),
});

However this gives the following error:

Error: Invalid reference exceeds the schema root: ref:type

This kinda makes sense as an error but I don't know how to restructure this to get it to apply the selector at the root.

Im using latest JOI (16.0.1)

like image 883
Not loved Avatar asked Sep 15 '19 22:09

Not loved


People also ask

Is not allowed to be empty in Joi?

Well, turns out that Joi doesn't allow empty strings when you put Joi. string() - even though I didn't specifically make it a required field and all validations are optional by default.


1 Answers

This can be resolved by prefixing the key name passed to .when() with a ., to denote the key as being relative to the object being validated:

Joi.object({
  type: Joi.string().valid('a','b').required(),
  thing: Joi.number().required()
})
.when('.type', {  /* <-- prefix with . */
  switch : [
    { is: 'a', then: Joi.object({ foo: Joi.string() }) },
    { is: 'b', then: Joi.object({ bar: Joi.number() }) },]
})

Here's a working example - hope that helps :-)

like image 112
Dacre Denny Avatar answered Oct 08 '22 18:10

Dacre Denny