I have the following validation on one of my routes:
payload: {
keywordGroups: Joi.array().items(Joi.object().keys({
language: Joi.string().required(),
containsAny: Joi.array().items(Joi.string()).default([]).when('containsAll', { is: [], then: Joi.required() }),
containsAll: Joi.array().items(Joi.string()).default([]).when('containsAny', { is: [], then: Joi.required() }),
notContainsAll: Joi.array().items(Joi.string()).default([]),
notContainsAny: Joi.array().items(Joi.string()).default([])
})).required(),
}
I'm trying to make it so that containsAny
or containsAll
have to include at least one string. If containsAny
is empty, containsAll
should have at least one item. And if containsAll
is empty, containsAny
should at least include one item.
But it seems Joi.when
doesn't really work when it es to an array of objects.
I have the following validation on one of my routes:
payload: {
keywordGroups: Joi.array().items(Joi.object().keys({
language: Joi.string().required(),
containsAny: Joi.array().items(Joi.string()).default([]).when('containsAll', { is: [], then: Joi.required() }),
containsAll: Joi.array().items(Joi.string()).default([]).when('containsAny', { is: [], then: Joi.required() }),
notContainsAll: Joi.array().items(Joi.string()).default([]),
notContainsAny: Joi.array().items(Joi.string()).default([])
})).required(),
}
I'm trying to make it so that containsAny
or containsAll
have to include at least one string. If containsAny
is empty, containsAll
should have at least one item. And if containsAll
is empty, containsAny
should at least include one item.
But it seems Joi.when
doesn't really work when it es to an array of objects.
- Try swapping your is: [] for Joi.array().length(0). the documentation suggests the is condition should be a Joi type. github./hapijs/joi/blob/master/API.md#anywhenref-options – Cuthbert Commented Nov 18, 2015 at 21:38
- I think you're also creating a circular dependency here. see this thread: github./hapijs/joi/issues/588 – Cuthbert Commented Nov 18, 2015 at 21:42
- @Cuthbert I think my main question was on how I could reference those fields correctly, seeing that they're in an array of objects. – woutr_be Commented Nov 19, 2015 at 5:16
1 Answer
Reset to default 6You need to use Joi.alternatives()
otherwise you will create a circular dependency as described in this issue.
In your is
condition in the when()
, you need to specify a Joi type instead of just an empty array. This example works:
import * as Joi from 'joi';
var arraySchema = Joi.array().items(Joi.object().keys({
first: Joi.array().items(Joi.number()).default([])
.when('second', {is: Joi.array().length(0), then: Joi.array().items(Joi.number()).required().min(1)}),
second: Joi.array().items(Joi.number()).default([])
}));
var altArraySchema = Joi.array().items(Joi.object().keys({
first: Joi.array().items(Joi.number()).default([]),
second: Joi.array().items(Joi.number()).default([])
.when('first', {is: Joi.array().length(0), then: Joi.array().items(Joi.number()).required().min(1)}),
}));
var obj = [
{
first: [],
second: []
}
];
var finalSchema = Joi.alternatives(arraySchema, altArraySchema);
var result = Joi.validate(obj, finalSchema);
console.log(JSON.stringify(result, null, 2));
The variable obj
will fail the validation because both first
and second
are empty. Making either of them non-empty will pass the validation check.