Search code examples
javascriptnode.jshapi.jsjoi

Joi validator conditional schema


I need to create dynamic schema to validate my api request query in node js using Joi validator depending on a key in the request query. Say the following below mentioned pattern are my valid queries.

I'm using hapi/joi version 16.1.8

Combination 1

{ type: 1, firstname: 'user first name', lastname: 'user last name'}

Combination 2

{ type: 2 , salary: 1000, pension: 200}

Combination 3

{ type: 3 , credit: 550, debit: 100}

As you can see the object keys varies depending on the value of type. How this can be handled properly?

We can handle two conditions using Joi.alternatives like

const schema = Joi.alternatives().conditional(Joi.object({ type: 1 }).unknown(), {
    then: Joi.object({
        type: Joi.string(),
        firstname: Joi.string(),
        lastname: Joi.string()
    }),
    otherwise: Joi.object({
        type: Joi.number(),
        salary: Joi.any(),
        pension: Joi.any()
    })
});

But how this can be done for 3 conditions?


Solution

  • I achieved the same in a little different manner. Posting the same here since this might be useful for someone in future.

    const schema = Joi.object({
        type: Joi.number().required().valid(1, 2, 3),
        firstname: Joi.alternatives().conditional('type', { is: 1, then: Joi.string().required() }),
        lastname: Joi.alternatives().conditional('type', { is: 1, then: Joi.string().required() }),
        salary: Joi.alternatives().conditional('type', { is: 2, then: Joi.number().required() }),
        pension: Joi.alternatives().conditional('type', { is: 2, then: Joi.number().required() }),
        credit: Joi.alternatives().conditional('type', { is: 3, then: Joi.number().required() }),
        debit: Joi.alternatives().conditional('type', { is: 3, then: Joi.number().required() }),
    }))
    

    This was working perfectly as expected.

    When the type value is 1 the object should have only type, firstname and lastname

    When the type value is 2 the object should have only type, salary and pension

    When the type value is 3 the object should have only type, credit and debit

    Any other combination will be thrown as error from the joi validator middleware layer. Also any other type value other that 1, 2 and 3 will be throwing error.