I am having an array of objects to validate from the specific schemas and if any of the objects matches with the given schemas, I want to validate against it and ignore other schemas and move to next array item.
I tried Joi.alternatives but it will go and check against all the schemas instead of checking only one if it got matched.
My validator:
Joi.array().min(1).max(49).items(Joi.object({
type: Joi.number().valid([1, 2, 3, 4]).required()
}).when(Joi.object({
type: Joi.number().valid(1)
}).unknown(), {
then: profile1
}).when(Joi.object({
type: Joi.number().valid(2)
}).unknown(), {
then: profile2
}).when(Joi.object({
type: Joi.number().valid(3)
}).unknown(), {
then: profile3
}))
Profile1//type1
export default Joi.object().keys({
type: Joi.number().valid([1, 2, 3]).required(),
surname: Joi.string().max(50).allow(""),
givenname: Joi.string().max(50).allow("")
}).unknown(true)
Profile2//type2
export default Joi.object().keys({
type: Joi.number().valid([1, 2, 3]).required(),
address: Joi.string().max(50).allow(""),
initialname: Joi.string().max(50).allow(""),
surname: Joi.string().max(50).allow(""),
data: Joi.array.min(1).max(29).items(Joi.object({
code: Joi.string().max(20).allow(""),
number: Joi.string().max(20).allow(""),
}),
address1: Joi.array.min(1).max(29).items(Joi.object({
city: Joi.string().max(20).allow(""),
postal: Joi.string().max(20).allow(""),
})
}).unknown(true)
Profile3//type3
export default Joi.object().keys({
type: Joi.number().valid([1, 2, 3]).required(),
units: Joi.string().max(50).allow(""),
others: Joi.string().max(50).allow(""),
surname: Joi.string().max(50).allow(""),
data2: Joi.array.min(1).max(29).items(Joi.object({
sub1: Joi.string().max(20).allow(""),
sub2: Joi.string().max(20).allow(""),
}),
additional: Joi.array.min(1).max(29).items(Joi.object({
data1: Joi.string().max(20).allow(""),
data2: Joi.string().max(20).allow(""),
})
}).unknown(true)
- If profile1 gets matched how I can only validate that and avoid others
- Same when I have multiple arrays of objects only validate against the specific profiles
sample object:
[
{
"type":1,
"surname":"",
"givenname":""
},
{
"type":2,
"surname":"val",
"address":"testte",
"initialname":"test",
"data":[{
"code":"test",
"number":"test"
}],
"address1":[{
"city":"test",
"postal":123
}
}],
{
"type":"3",
"surname":"",
"units":"",
"others":"",
"data2":[{
"sub1":"test",
"sub2":"test"
}],
"additionals":[{
"data1":"test",
"data2":123
}]
}
]
here profile1 gets matched with given data so it should validate against it and ignore profile2 and profile3 (also validate type is number)
here profile2 gets matched with given data so it should validate against it and ignore profile1 and profile3 (also validate type is number)
now it should move to the next object from the array where type is not number so it should not check schema and throw an error
Note: I am using Joi version 13.4.0
CodePudding user response:
There are some typos in your files and validators.
First of Joi.array is a function and needs to be called as one.
// This is incorrect
data2: Joi.array
...
additional: Joi.array
// Should be changed to this where array is invoked as a function
data2: Joi.array()
...
additional: Joi.array()
Additionally, I've added a fourth validator which basically passes all sample objects which have a type greater than 3.
.when(
Joi.object({
type: Joi.number().greater(3),
}).unknown(),
{
then: Joi.object().unknown(true),
}
)
And there are other typos in your validators e.g missing brackets - I created a fixed version of your validator in codesandbox.
Validation is still failing in the codesandbox since in profile2.js postal is declared as string, but in your samples array it is a number for the second object, search for postal: 123 and change it to postal: "123" or modify the validation of postal from postal: Joi.string() to postal: Joi.number()
This way if one of the validators passes then the other ones won't throw an error, and if the type is greater than 3 it will pass validation.