Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hapi/Joi validation with nested object

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 comes to an array of objects.

like image 883
woutr_be Avatar asked Nov 18 '15 02:11

woutr_be


1 Answers

You 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.

like image 184
Cuthbert Avatar answered Oct 10 '22 11:10

Cuthbert