我们如何为不同的请求类型编写一个 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)
我一直在尝试创建一个架构。它代表我的对象,就像 {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)