我们如何为不同的请求类型编写一个 Joi 模式?

How can we write a Joi schema for different request types?

我一直在尝试创建一个架构。它代表我的对象,就像 {name:"Joe Doe", id:"1234567890"} 但是在第一个创建新对象的请求上;它不应该在对象中有 id 参数。否则它可能意味着对消费者的更新......

您对实现它的最佳方式有什么想法吗?

我需要什么作为 joi 模式;

joi.object().keys({
    id: joi.string().forbidden() or required(),
    name: joi.string(),
    ...

样品请求;

创建:

POST 请求... 'api/v1/item/'

对象:{name:"Joe Doe"}

更新:

PUT 请求... 'api/v1/item/'

对象:{id:"1234567890", name:"Joe Doe"}

我的应用程序有相同的用例,我所做的是在 Joi 上下文中添加一个标志

const conditionalIdValue = Joi.any().when('$isEditForm', {
  is: Joi.boolean()
    .valid(true)
    .required(),
  then: Joi.string()
    .required(),
  otherwise: Joi.forbidden(),
});

const schema = joi.object().keys({
  id: conditionalIdValue,
  name: joi.string(),
  ...
});

在我调用 Joi.validate 的地方,我可以自己访问请求,因此您可以在上下文中附加 isEditForm 和正确的值。

// validation middleware

export const validationMiddleWare = async (req, res, next) => {
  try {
    req.body = await Joi.validate(req.body, schema, {
      context: { isEditForm: req.method === 'POST' },
    });
    return next();
  } catch (e) {
    // reject the request
  }
};

您可以在调用验证方法时使用 Joi 的上下文选项。像

var Joi = require("@hapi/joi");

const schema = Joi.when(Joi.ref("$method"), {
          "is": "put",
          "then": Joi.object().keys({
            "id": Joi.string().required(),
            "name": Joi.string()
          }),
          "otherwise": Joi.object().keys({
            "id": Joi.string().forbidden(),
            "name": Joi.string()
          })
        });

function validate() {
    const result = schema.validate({"id": "123", "name": "myname"}, {"context": {"method": "put"}});
    console.log(result);
}

validate();

如果您将方法作为 put 传递,它将使用 put 模式 else post 模式。

在项目上,我们仍然使用14.3.1版本的joi。 我可以通过创建基本 joi 对象并像这样扩展它来解决我的问题;

const base = joi.object().keys({name: joi.string()});
const put = base.keys({
    id: joi.string().required(),
});
const post = base.keys({
    id: joi.string().forbidden(),
});

甚至阅读起来看起来更干净。如果有人需要类似的东西,我会把它留在这里。

const Joi = require("joi");

const schema = Joi.object().keys({
   //General attributes that will be required in all put/post request
  noOfCopies: Joi.number().required(),
});

const put = schema.keys({
    customerId: Joi.string().required().forbidden(),
    movieId: Joi.string().required().forbidden(),
});

const post = schema.keys({
  customerId: Joi.string().required(),
  movieId: Joi.string().required(),
});

function validator(payload,method) {
  
  const validationMethod = (method === "POST" ) ? post : put ;
  const { error } = validationMethod.validate(payload);

  return error;
}

module.exports = validator;


//In Your Controller
validator(req.body,req.method)