Vishnu
Vishnu

Reputation: 724

joi validation based on array object property value

I have a set of data to validate:

{
   "createUser": {
     "isCustomer": true or false,
     "data": {
       "product": [ // sometimes array of object with id : 3
        {
         "id":46,
         "sumInsured":"4562000",
        },
        {
         "id":45,
         "sumInsured":"8532000",
        },
        ]
   }
}

These are the following scenarios we need to validate:

1) validate array of objects
2) isCustomer is mandatory when id is 45
3) isCustomer not allowed when id is 3

First is done:

Joi.object({
  data: Joi.array()
        .items({
          id: Joi.number().valid(3,45,46)
            .required(),
          sumInsured: Joi.string()
            .required()
        }),
})

I searched a lot regarding the same, but still not able to find a solution for the same.

Any help would be really appreciated.

Thanks in advance.

Upvotes: 2

Views: 2889

Answers (1)

Denis Tsoi
Denis Tsoi

Reputation: 10404

This a combined Schema for both points 2 & 3.

You will need to use the method .when - which will define your first if condition. From there, you will have to include another .when to add your second if condition

Such that

.when("data", {
  is: <first if condition>,
  then: <first if condition do something>
  otherwise: .when("data",{
    is: <else if>
    then: <else if do something>
  })
})

To understand the above logically, it would result in the following

Joi.any().when("data", {
  is: <is id 45?>,
  then: <is required>
  otherwise: Joi.any().when("data",{
    is: <is id 3?>
    then: <is forbidden>
  })
})

Test cases

const test_id_3_ok = {
  createUser: {
    data: {
      product: [
        {
          id: 3,
        },
      ],
    },
  },
};

const test_id_46_ok = {
  createUser: {
    data: {
      product: [
        {
          id: 46,
        },
      ],
    },
  },
};

const test_id_46_has_customer_ok = {
  createUser: {
    isCustomer: true,
    data: {
      product: [
        {
          id: 46,
        },
      ],
    },
  },
};

const test_id_46_no_customer_ok = {
  createUser: {
    data: {
      product: [
        {
          id: 46,
        },
      ],
    },
  },
};


const test_id_3_has_customer_should_error = {
  isCustomer: true,
  createUser: {
    data: {
      product: [
        {
          id: 3,
        },
      ],
    },
  },
};

const test_id_45_ok = {
  createUser: {
    isCustomer: true,
    data: {
      product: [
        {
          id: 45,
        },
      ],
    },
  },
};

const test_id_45_no_customer_should_error = {
  createUser: {
    data: {
      product: [
        {
          id: 45,
        },
      ],
    },
  },
};

Schema

const dataSchema = Joi.object({
  product: Joi.array().items(
    Joi.object({
      id: Joi.number().valid(3, 45, 46),
    })
  ),
});

const mandatory = (value) =>
  Joi.object({
    product: Joi.array().items(
      Joi.object({
        id: Joi.number().valid(value),
      })
    ),
  });

const schema = Joi.object({
  createUser: Joi.object({
    isCustomer: Joi.any().when("data", {
      is: mandatory(3),
      then: Joi.forbidden(),
      otherwise: Joi.any().when("data", {
        is: mandatory(45),
        then: Joi.bool().required(),
      }),
    }),

    data: dataSchema,
  }),
});

schema.validate(test_id_3_ok) //?
schema.validate(test_id_3_has_customer_should_error);  //?

schema.validate(test_id_45_ok); //?
schema.validate(test_id_45_no_customer_should_error); //?

schema.validate(test_id_46_ok); //?
schema.validate(test_id_46_has_customer_ok); //?
schema.validate(test_id_46_no_customer_ok); //?

Upvotes: 2

Related Questions