john maccarthy
john maccarthy

Reputation: 6313

Joi - make everything required by default?

I'm building out a Node/Express API and using Joi for validation. It's a great package and has been incredibly useful. However, we're getting tired of doing things like:

const mySchema = joi.object({
    thing1: joi.string().required(),
    thing2: joi.string().required(),
    thing3: joi.string().required(),
    thing4: joi.string().required(),
    thing5: joi.string().required(),
}).required();

We'd like everything to be required by default, and manually call .optional to override that. In fact this seems a sensible default - but leaving that aside for now.

Is there a way to achieve this?

Upvotes: 12

Views: 6218

Answers (2)

FINDarkside
FINDarkside

Reputation: 2435

You can use presence option to make fields required by default. Example:

const mySchema = joi.object({
    thing1: joi.string(),
    thing2: joi.string(),
    thing3: joi.string(),
    thing4: joi.string(),
    thing5: joi.string(),
}).options({ presence: 'required' }).required();

Upvotes: 24

Anand Undavia
Anand Undavia

Reputation: 3543

There does not exist a standard way of making every key required, but there are workarounds.
One of the workaround can be usage of .requiredKeys() and .optionalKeys() on Joi.object()

Have a look at .describe() function,
It returns an object which has a key flags.
When a key is marked as 'optional', we get flags.presence = 'optional'

Using that information, you can call .describe() on each key and prepare two arrays of requiredKey and optionalKeys

And then, you can pass those arrays to .requiredKeys() and .optionalKeys() respectively.

For example:
Say you define your joi schema as:

const joiSchemaKeys = {
    thing1: Joi.string(),
    thing2: Joi.string().optional(),
    thing3: Joi.string(),
    thing4: Joi.string(),
    thing5: Joi.string().required()
};

You can then prepare two arrays optionalKeys and requiredKeys using this:

const initialKeyInformation = {
    requiredKeys: [],
    optionalKeys: []
};

const prepareKeysInformation = keys =>
    Object.keys(keys).reduce((accumulated, aKey) => {
        const description = keys[aKey].describe();
        const isMarkedOptional =
            description.flags &&
            description.flags.presence &&
            description.flags.presence === "optional";

        if (isMarkedOptional) {
            console.log(`"${aKey}" is marked optional`);
            accumulated.optionalKeys.push(aKey);
        } else {
            console.log(`"${aKey}" is not marked, making it required`);
            accumulated.requiredKeys.push(aKey);
        }
        return accumulated;
    }, initialKeyInformation);

const { optionalKeys, requiredKeys } = prepareKeysInformation(joiSchemaKeys);

Once that is done, you can prepare your joi schema like:

const schema = Joi.object()
    .keys(joiSchemaKeys)
    .requiredKeys(requiredKeys)
    .optionalKeys(optionalKeys);

So this way, you will make every key required unless specified otherwise.

Upvotes: 0

Related Questions