admin管理员组

文章数量:1221403

I'm attempting to use Joi to validate a data model accepted by a RESTful web service.

For a create operation, I want to enforce the "required" validation on fields. However, for an update operation, a partial data object may be submitted so I would like the "required" attributes to be ignored.

Is there a way to achieve this aside from creating two schemas?

I'm attempting to use Joi to validate a data model accepted by a RESTful web service.

For a create operation, I want to enforce the "required" validation on fields. However, for an update operation, a partial data object may be submitted so I would like the "required" attributes to be ignored.

Is there a way to achieve this aside from creating two schemas?

Share Improve this question edited May 21, 2015 at 20:25 jeremy303 asked May 21, 2015 at 20:18 jeremy303jeremy303 9,24114 gold badges75 silver badges102 bronze badges 2
  • can you just remove required? – Giuseppe Pes Commented May 21, 2015 at 20:21
  • 1 During creation, I want to enforce required. Lacking an option to ignore required during validation, I'm thinking I may need to create two schemas-- one for creation, another for updates. – jeremy303 Commented May 21, 2015 at 20:28
Add a comment  | 

5 Answers 5

Reset to default 5

With .fork() you can pass in an array of the fields you want to be required.

const validate = (credentials, requiredFields = []) => {

  // Schema
  let userSchema = Joi.object({
    username: Joi.string(),
    email: Joi.string().email(),
  })

  // This is where the required fields are set
  userSchema = userSchema.fork(requiredFields, field => field.required())

  return userSchema.validate(credentials)
}

validate(credentials, ['email'])

Or do the opposite and change them to optional.

You can avoid the two schemas by extending the first one using optionalKeys.

const createSchema = Joi.object().keys({
  name: Joi.string().required(),
  birthday: Joi.date().required(),
});

const updateSchema = createSchema.optionalKeys("name", "birthday");

Joi.validate({name: "doesn't work"}, createSchema); // error: birthday field missing
Joi.validate({name: "it works"}, updateSchema); // all good

Your desired results can be achieved using the alter method. Here's an example.

const validateUser = (user, requestType) => {
  let schema = Joi.object({
    email: Joi.string().email().required(),
//Here, we want to require password when request is POST. 
//Also we want to remove password field when request is PUT
    password: Joi.string()
      .min(1)
      .max(256)
      .alter({
//For POST request
        post: (schema) => schema.required(),
//For PUT request
        put: (schema) => schema.forbidden(),
      }),
  });

  return schema.tailor(requestType).validate(user);
};

Then in our route we call the function and pass the arguments like so:

//For POST
const { error } = validateUser({email: "[email protected]"}, "post");//error: "password is a required field" 
//For PUT 
const { error } = validateUser({email: "[email protected]"}, "put");//error: undefined (no error)

use .when() and set .required() according to the conditions.

You can skip Joi validation by replace Joi.string()... to the exact value which you are passing as username. In the example i have passed empty username to api.

Also in condition basis, you can skip joi validation

let userSchema = Joi.object({
   username: "",
   email: <some condition> === true ? "" : Joi.string().required()
})

本文标签: javascriptIgnoring quotrequiredquot in Joi validationStack Overflow