Keerthivasan
Keerthivasan

Reputation: 12880

Joi validation - field required condition at runtime

I'm using hapijs to write a microservice. I have an API that takes three parameters in the request body (POST method)

I'm planning to do validation using JOI. The validation should be the following

  1. The UserID should be required if both last name and date of birth are absent in the request

  2. Both Last name and date of birth should be required if UserID is absent

I have tried to achieve that by following. It doesn't seem to work.

export const userRequestModel = Joi.object().keys({
    lastname: Joi.string().when('uid',
        {
            is: undefined,
            then: Joi.string().required()
        }),
    dob: Joi.string().when('uid',
        {
            is: undefined,
            then: Joi.string().required()
        }),
    uid: Joi.string().
        when('lastname',
        {
            is: undefined,
            then: Joi.string().required()
        }).
        concat(Joi.string().when('dob',
            {
                is: undefined,
                then: Joi.string().required()
            }))
});

The concatenation doesn't seem to be syntactically correct. It shows the below typing error

Argument of type 'AlternativesSchema' is not assignable to parameter of type 'FunctionSchema'.Property 'arity' is missing in type 'AlternativesSchema'.

Upvotes: 4

Views: 3031

Answers (1)

Ankh
Ankh

Reputation: 5718

Fundamentally this schema creates a circular dependency.

Error: item added into group uid created a dependencies error

...an issue Joi has no elegant way of managing, especially when there's more than two keys. An extended discussion can be found here amongst other places.

A possible alternative would be something along the lines of:

Joi.alternatives().try(
    Joi.object().keys({
        lastname: Joi.string().min(1).required(),
        dob: Joi.string().min(1).required(),
        uid: Joi.string()
    }),
    Joi.object().keys({
        lastname: Joi.string(),
        dob: Joi.string(),
        uid: Joi.string().min(1).required()
    })
);

Which isn't pretty and could fall apart if the schema got more complex.

Upvotes: 1

Related Questions