Search code examples
javascriptnode.jsjoi

Conditional array items with Joi


I have an issue to create Joi schema for this input

{
  projects: ["*","ABC123","ABC456"]
}

With the input above, it should throw an error.

I did try to use Joi.alternatives() like this

const schema = Joi.object({
  projects: 
    Joi.array()
    .items(
      Joi.alternatives(
        Joi.string().equal('*'), 
        Joi.string().regex(new RegExp(/^ABC_([0-9]{3,3})$/))
      )
    )
})

but it appears to allow both ["*"] and ["ABC123","DEF456"] together. I wanted it to be either ["*"] or ["ABC123","DEF456"], else it will be an error.

How can I actually achieve it by using Joi?


Solution

  • You can try something like this:

    const schema = Joi.object({
      projects: Joi.alternatives(
        Joi.array().length(1).items(
          Joi.string().equal('*')
        ),
        Joi.array().items(
          Joi.string().regex(/^ABC[0-9]{3}$/)
        )
      )
    });
    

    That is, havingh two alternative array schemas instead of having a single array schema with alternative schemas of elements.

    The .length(1) is there to reject values like ["*", "*"] if you want to reject arrays like that, but could be omitted otherwise.

    Also, the regex could be written in a simpler way so I simplified it, but I guess that it was just an example so that is not so important. What is important though is that i removed the underscore ("_") from the regex, because a regex in your example didn't match values like "ABC123" in your example but e.g. "ABC_123".