在Node.js RESTapi中验证用户的输入似乎非常简单Joi
.
但问题是我的应用程序不是用英文写的.这意味着我需要向前端用户发送自定义书面消息.
我搜索了这个,只发现了问题.
也许有人可以为此提供解决方案?
这是我用来验证Joi
系统的代码:
var schema = Joi.object().keys({
firstName: Joi.string().min(5).max(10).required(),
lastName: Joi.string().min(5).max(10).required()
..
});
Joi.validate(req.body, schema, function(err, value) {
if (err) {
return catched(err.details);
}
});
function catched(reject) {
res.json({
validData: false,
errors: reject
});
}
Run Code Online (Sandbox Code Playgroud)
另外,有没有办法Joi
在客户端使用?
谢谢!
Rvy*_*dey 63
原答案:
目前的方法(我个人觉得它更好)是使用.messages()
(或.prefs({messages})
)。
const Joi = require('@hapi/joi');
const joiSchema = Joi.object({
a: Joi.string()
.min(2)
.max(10)
.required()
.messages({
'string.base': `"a" should be a type of 'text'`,
'string.empty': `"a" cannot be an empty field`,
'string.min': `"a" should have a minimum length of {#limit}`,
'any.required': `"a" is a required field`
})
});
const validationResult = joiSchema.validate({ a: 2 }, { abortEarly: false });
console.log(validationResult.error); // expecting ValidationError: "a" should be a type of 'text'
Run Code Online (Sandbox Code Playgroud)
的使用.errors()
是不建议只是使用定制信息更新默认消息。
.prefs({ messages })
是一种提供更多选项作为首选项的精心设计的方法。prefs 的其他选项直接取自.validate() 的选项
进一步阅读:https : //github.com/hapijs/joi/issues/2158
更新 1:我看到上面的解释对某些人不起作用,所以我放了一些代码来测试自己。在这里检查:https : //runkit.com/embed/fnfaq3j0z9l2
还更新了之前共享的代码片段,以包含从包包含、使用到调用实际验证方法的详细信息。
更新 2: joi 错误类型列表及其描述(.messages()
例如 string.base、array.unique、date.min 等)可在此处获得。
更新 3:Joi已从 hapi 项目转移到独立项目:https : //www.npmjs.com/package/joi。确保您使用的是最新版本(或至少高于 v17)。
Chr*_*alo 36
我必须深入研究源代码才能找到如何进行与上下文相关的消息模板/格式设置的示例,因为它似乎没有记录:
\nmessages: {\n \'string.alphanum\': \'{{#label}} must only contain alpha-numeric characters\',\n \'string.base\': \'{{#label}} must be a string\',\n \'string.base64\': \'{{#label}} must be a valid base64 string\',\n \'string.creditCard\': \'{{#label}} must be a credit card\',\n \'string.dataUri\': \'{{#label}} must be a valid dataUri string\',\n \'string.domain\': \'{{#label}} must contain a valid domain name\',\n \'string.email\': \'{{#label}} must be a valid email\',\n \'string.empty\': \'{{#label}} is not allowed to be empty\',\n \'string.guid\': \'{{#label}} must be a valid GUID\',\n \'string.hex\': \'{{#label}} must only contain hexadecimal characters\',\n \'string.hexAlign\': \'{{#label}} hex decoded representation must be byte aligned\',\n \'string.hostname\': \'{{#label}} must be a valid hostname\',\n \'string.ip\': \'{{#label}} must be a valid ip address with a {{#cidr}} CIDR\',\n \'string.ipVersion\': \'{{#label}} must be a valid ip address of one of the following versions {{#version}} with a {{#cidr}} CIDR\',\n \'string.isoDate\': \'{{#label}} must be in iso format\',\n \'string.isoDuration\': \'{{#label}} must be a valid ISO 8601 duration\',\n \'string.length\': \'{{#label}} length must be {{#limit}} characters long\',\n \'string.lowercase\': \'{{#label}} must only contain lowercase characters\',\n \'string.max\': \'{{#label}} length must be less than or equal to {{#limit}} characters long\',\n \'string.min\': \'{{#label}} length must be at least {{#limit}} characters long\',\n \'string.normalize\': \'{{#label}} must be unicode normalized in the {{#form}} form\',\n \'string.token\': \'{{#label}} must only contain alpha-numeric and underscore characters\',\n \'string.pattern.base\': \'{{#label}} with value {:[.]} fails to match the required pattern: {{#regex}}\',\n \'string.pattern.name\': \'{{#label}} with value {:[.]} fails to match the {{#name}} pattern\',\n \'string.pattern.invert.base\': \'{{#label}} with value {:[.]} matches the inverted pattern: {{#regex}}\',\n \'string.pattern.invert.name\': \'{{#label}} with value {:[.]} matches the inverted {{#name}} pattern\',\n \'string.trim\': \'{{#label}} must not have leading or trailing whitespace\',\n \'string.uri\': \'{{#label}} must be a valid uri\',\n \'string.uriCustomScheme\': \'{{#label}} must be a valid uri with a scheme matching the {{#scheme}} pattern\',\n \'string.uriRelativeOnly\': \'{{#label}} must be a valid relative uri\',\n \'string.uppercase\': \'{{#label}} must only contain uppercase characters\'\n}\n
Run Code Online (Sandbox Code Playgroud)\n使用模板化消息的示例:
\nconst Joi = require("joi");\n\nconst schema = Joi.object({\n nested: Joi.object({\n name: Joi.string().required().messages({\n "any.required": "{{#label}} is required!!",\n "string.empty": "{{#label}} can\'t be empty!!",\n }),\n }),\n});\n\nconst result = schema.validate({\n nested: {\n // comment/uncomment to see the other message\n // name: "",\n },\n});\n\nconsole.log(result.error.details);\n
Run Code Online (Sandbox Code Playgroud)\n使用模板语法时,似乎传递的上下文值如下所示,尽管特定规则/验证器可能会传递更多上下文:
\n{\n \xe2\x80\x8bkey: "name", // this key, without ancestry\n \xe2\x80\x8blabel: `"nested.name"`, // full path with dots as separators, in quotes\n \xe2\x80\x8bvalue: "", // the value that was validated\n}\n
Run Code Online (Sandbox Code Playgroud)\n
Ash*_*dam 25
Joi版本14.0.0
const SchemaValidation = {
coins: Joi.number()
.required()
.error(() => {
return {
message: 'Coins is required.',
};
}),
challenge_name: Joi.string()
.required()
.error(() => {
return {
message: 'Challenge name is required.',
};
}),
challengeType: Joi.string()
.required()
.error(() => {
return {
message: 'Challenge type is required.',
};
}),
challengeDescription: Joi.string()
.required()
.error(() => {
return {
message: 'Challenge description is required.',
};
}),
};
Run Code Online (Sandbox Code Playgroud)
在错误对象中,您可以获取错误类型并根据错误信息进行更改。
Gui*_*rez 24
扩展Ashish Kadam的答案,如果您有许多不同的错误类型,则可以检查存在哪种错误,并相应地设置其消息:
var schema = Joi.object().keys({
firstName: Joi.string().min(5).max(10).required().error(errors => {
errors.forEach(err => {
switch (err.type) {
case "any.empty":
err.message = "Value should not be empty!";
break;
case "string.min":
err.message = `Value should have at least ${err.context.limit} characters!`;
break;
case "string.max":
err.message = `Value should have at most ${err.context.limit} characters!`;
break;
default:
break;
}
});
return errors;
}),
// ...
});
Run Code Online (Sandbox Code Playgroud)
您可以在此处检查错误列表:Joi 14.3.1 API参考>错误>错误列表
您也可以查看any.error
参考资料以获取更多信息。引用文档:
如果规则失败,则使用自定义错误覆盖默认的joi错误:
err
可:
- 的实例
Error
-覆盖错误。- 一种
function(errors)
,以错误数组作为参数,它必须是:
- 返回一个
string
-用此文本替换错误消息- 返回单个
object
或其中一个Array
,其中:
type
-提供错误类型的可选参数(例如number.min
)。message
-如果template
提供了可选参数(包含错误文本)。template
-如果message
提供了可选参数(包含模板字符串),则使用与通常的joi语言错误相同的格式。context
-可选参数,如果使用,则为错误提供上下文template
。Error
与直接提供时一样,返回-Error
,但是您可以根据错误来自定义错误消息。options
:
self
-布尔值,指示是将错误处理程序用于所有错误,还是仅用于此属性上发生的错误(true
值)。这个概念仅对array
或object
模式有意义,因为其他值没有子级。默认为false
。
Raz*_*Raz 15
我找到的解决方案是设置:
var schema = Joi.object().keys({
firstName: Joi.string().min(5).max(10).required().label("Your error message in here"),
lastName: Joi.string().min(5).max(10).required()
..
});
Run Code Online (Sandbox Code Playgroud)
然后label
从回调error
变量中打印出来
Nit*_*Joy 11
您还可以显示特定属性的消息
const Joi = require('Joi');
const schema = Joi.object({
username: Joi.string()
.min(2)
.max(30)
.required()
.pattern(new RegExp(/^(?!.*\.\.)(?!.*\.$)[^\W][\w.]{0,29}$/))
.message({"string.pattern.base":"Invalid username",
"string.min":"minimum 2 character required",
"string.max":"maximum 30 characters allowed"})
});
Run Code Online (Sandbox Code Playgroud)
您可以参考此消息对象键。
messages: {
'any.custom': [Object],
'any.default': [Object],
'any.failover': [Object],
'any.invalid': [Object],
'any.only': [Object],
'any.ref': [Object],
'any.required': [Object],
'any.unknown': [Object],
'string.alphanum': [Object],
'string.base': [Object],
'string.base64': [Object],
'string.creditCard': [Object],
'string.dataUri': [Object],
'string.domain': [Object],
'string.email': [Object],
'string.empty': [Object],
'string.guid': [Object],
'string.hex': [Object],
'string.hexAlign': [Object],
'string.hostname': [Object],
'string.ip': [Object],
'string.ipVersion': [Object],
'string.isoDate': [Object],
'string.isoDuration': [Object],
'string.length': [Object],
'string.lowercase': [Object],
'string.max': [Object],
'string.min': [Object],
'string.normalize': [Object],
'string.token': [Object],
'string.pattern.base': [Object],
'string.pattern.name': [Object],
'string.pattern.invert.base': [Object],
'string.pattern.invert.name': [Object],
'string.trim': [Object],
'string.uri': [Object],
'string.uriCustomScheme': [Object],
'string.uriRelativeOnly': [Object],
'string.uppercase': [Object]
}
Run Code Online (Sandbox Code Playgroud)
你可以使用.error(new Error('message')),它可以为我工作
var schema = Joi.object().keys({
firstName: Joi.string().min(5).max(10).required().error(new Error('Give your error message here for first name')),
lastName: Joi.string().min(5).max(10).required().error(new Error('Give your error message here for last name'))
..
});
Joi.validate(req.body, schema, function(err, value) {
if (err) {
console.log(err.message)
return catched(err.message);
}
});
Run Code Online (Sandbox Code Playgroud)
小智 5
添加自定义消息的解决方案:
只需添加另一个链式函数即可在定义架构时抛出错误。
在你的情况下
firstName: Joi.string().min(5).max(10).required().error(new Error('I am a custom error and I know it!')),
Run Code Online (Sandbox Code Playgroud)
休息将保持不变。
在客户端使用 Joi 的解决方案 (您的第二个问题)
Joi-Browser 是允许在客户端使用相同模式的包。
这是一个有趣的讨论,你可以看看。
干杯!