Reputation: 6736
I have a nested schema setup like this:
var schema = Joi.object().keys({
first_name: Joi.string().required(),
last_name: Joi.string().required(),
address: Joi.object().keys({
street: Joi.string().required(),
zip: Joi.number().required(),
state: Joi.string().required(),
country: Joi.string().required()
}).required(),
})
var options = { abortEarly: false };
var result = Joi.validate({}, schema, options);
When running this, result.error
will return the message:
[
{message: '"first_name" is required', path: 'first_name' },
{message: '"last_name" is required', path: 'last_name' },
{message: '"address" is required', path: 'address' }
]
As you see, the address
field is not expanded. I don't want to get a message that the whole address field is missing. Instead, I want to be informed about the individual items in the address schema missing. When I don't make address
explicitly required, the items in it don't get validated against required()
at all. The nested field validation seems to work only on the entire nested schema object level, not on the individual items within the schema level. How do I make it work with the individual nested schema items?
Upvotes: 4
Views: 2482
Reputation: 11585
Adding a "skeleton" object works. Working example here.
import Joi, {
string,
number,
object
} from "joi";
var schema = object({
first_name: string().required(),
last_name: string().required(),
address: object({
street: string().required(),
zip: number().required(),
state: string().required(),
country: string().required()
})/*.required(), <= Not needed */
})
var skeleton = { address: {} };
var options = { abortEarly: false };
var validate = data => {
var newData = Object.assign({}, skeleton, data);
return Joi.validate( newData, schema, options);
}
console.log(
JSON.stringify(validate({}).error.details, null, 2)
);
Result:
[
{
"message": "\"first_name\" is required",
"path": "first_name",
"type": "any.required",
"context": {
"key": "first_name"
}
},
{
"message": "\"last_name\" is required",
"path": "last_name",
"type": "any.required",
"context": {
"key": "last_name"
}
},
{
"message": "\"street\" is required",
"path": "address.street",
"type": "any.required",
"context": {
"key": "street"
}
},
{
"message": "\"zip\" is required",
"path": "address.zip",
"type": "any.required",
"context": {
"key": "zip"
}
},
{
"message": "\"state\" is required",
"path": "address.state",
"type": "any.required",
"context": {
"key": "state"
}
},
{
"message": "\"country\" is required",
"path": "address.country",
"type": "any.required",
"context": {
"key": "country"
}
}
]
Upvotes: 1