Node.js + Joi 如何显示自定义错误信息?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/48720942/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 18:40:46  来源:igfitidea点击:

Node.js + Joi how to display a custom error messages?

node.jsjoi

提问by Raz

It seems pretty straight forward to validate user's input in Node.js RESTapi with Joi.

在 Node.js RESTapi 中使用Joi.

But the problem is that my app is not written in English. That means I need to send a custom written messages to the frontend user.

但问题是我的应用程序不是用英文编写的。这意味着我需要向前端用户发送自定义的书面消息。

I have googled for this and only found issues.

我用谷歌搜索过这个,只发现了问题。

Maybe could someone give a solution for this?

也许有人可以为此提供解决方案?

This is the code I am using to validate with the Joisystem:

这是我用来验证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
      });
    }

Plus, is there a way to use Joiin client side?

另外,有没有办法Joi在客户端使用?

Thanks!

谢谢!

采纳答案by Raz

A solution I have found is to set:

我发现的一个解决方案是设置:

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()
  ..
});

Then print the labelfrom the callback errorvariable

然后label从回调error变量打印

回答by Ashish Kadam

Joi Version 14.0.0

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.',
      };
    }),
};

In errorsobject you can get, error type and change message according.

错误对象中,您可以获得错误类型和更改消息。

回答by Guillermo Gutiérrez

Extending on Ashish Kadam's answer, if you have many different error types, you can check which type of error is present, and set its message accordingly:

扩展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;
  }),
  // ...
});

You can check the list of errors here: Joi 14.3.1 API Reference > Errors > List of errors

您可以在此处查看错误列表:Joi 14.3.1 API 参考 > 错误 > 错误列表

Also you can check the any.errorreference for more information. Quoting the docs:

您也可以查看any.error参考资料以获取更多信息。引用文档:

Overrides the default joi error with a custom error if the rule fails where:

  • errcan be:
    • an instance of Error- the override error.
    • a function(errors), taking an array of errors as argument, where it must either:
      • return a string- substitutes the error message with this text
      • return a single objector an Arrayof it, where:
        • type- optional parameter providing the type of the error (eg. number.min).
        • message- optional parameter if templateis provided, containing the text of the error.
        • template- optional parameter if messageis provided, containing a template string, using the same format as usual joi language errors.
        • context- optional parameter, to provide context to your error if you are using the template.
      • return an Error- same as when you directly provide an Error, but you can customize the error message based on the errors.
  • options:
    • self- Boolean value indicating whether the error handler should be used for all errors or only for errors occurring on this property (truevalue). This concept only makes sense for arrayor objectschemas as other values don't have children. Defaults to false.

如果规则失败,则使用自定义错误覆盖默认的 joi 错误,其中:

  • err可:
    • Error- 覆盖错误的一个实例。
    • a function(errors),将一系列错误作为参数,它必须:
      • return a string- 用此文本替换错误消息
      • 返回单个object或其中一个Array,其中:
        • type- 提供错误类型的可选参数(例如。number.min)。
        • message- 如果template提供了可选参数,包含错误文本。
        • template- 提供了可选参数 if message,包含模板字符串,使用与通常的 joi 语言错误相同的格式。
        • context- 可选参数,如果您使用template.
      • 返回Error- 与直接提供时相同Error,但您可以根据错误自定义错误消息。
  • options
    • self- 布尔值,指示错误处理程序应用于所有错误还是仅用于此属性上发生的错误(true值)。这个概念只对arrayorobject模式有意义,因为其他值没有孩子。默认为false.

回答by Rvy Pandey

Edit:

编辑

Make sure you are using @hapi/joi- https://www.npmjs.com/package/@hapi/joi, version 16 and above.

确保您使用的是 -https @hapi/joi: //www.npmjs.com/package/@hapi/joi版本 16 及更高版本



Original answer:

原答案

The current way (I personally find it better) is to use .messages()(or .prefs({messages})).

目前的方法(我个人觉得它更好)是使用.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'

Usage of .errors()is not recommendedjust to update default message with custom message.

的使用.errors()不建议只是使用定制信息更新默认消息。

.prefs({ messages })is an elaborate way to provide more options as preferences. The other options for prefs are taken directly from options of .validate()

.prefs({ messages })是一种提供更多选项作为首选项的精心设计的方法。prefs 的其他选项直接取自.validate() 的选项

Further read: https://github.com/hapijs/joi/issues/2158

进一步阅读:https: //github.com/hapijs/joi/issues/2158



Update 1: I saw that the above explanation did not work out for some folks, so I have put up some code to test yourself. Check it here: https://runkit.com/embed/fnfaq3j0z9l2

更新 1:我看到上面的解释对某些人不起作用,所以我放了一些代码来测试自己。在这里检查:https: //runkit.com/embed/fnfaq3j0z9l2

Also updated the code snippet shared previously to have details from package inclusion, to usage, to calling the actual validation method.

还更新了之前共享的代码片段,以包含从包包含、使用到调用实际验证方法的详细信息。



Update 2: The list of joi error types and their description (for .messages()- like string.base, array.unique, date.min etc..) is available here.

更新 2: joi 错误类型列表及其描述(.messages()例如 string.base、array.unique、date.min 等)可在此处获得

回答by Sameer Ek

You can use .error(new Error('message')), And its work for me

你可以使用.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); 
  }
});

回答by Syeda Aimen Batool

Solution to add custom messages:Simply add another chained function to throw error while defining your schema.
In your case

添加自定义消息的解决方案:只需添加另一个链式函数即可在定义架构时抛出错误。
在你的情况下

 firstName: Joi.string().min(5).max(10).required().error(new Error('I am a custom error and I know it!')),

Rest will remain same.

休息将保持不变。

Solution to use Joi at client side(Your 2nd question)

在客户端使用 Joi 的解决方案(您的第二个问题)

Joi-Browseris the package which enables usage of the same schema at the client side.

Joi-Browser是允许在客户端使用相同模式的包。

Hereis an interesting discussion you can have a look at.

是一个有趣的讨论,你可以看看。

Cheers!

干杯!

回答by Max Sherbakov

let schema = Joi.object({ foo: Joi.number().min(0).error(() => '"foo" requires a positive number')});

let schema = Joi.object({ foo: Joi.number().min(0) .error(() => '"foo" 需要一个正数')});

Docs link

文档链接

回答by Csaba Varga

For anyone having a problem with

对于任何有问题的人

...messages is not a function

...消息不是函数

errors, you must install joiwith npm install @hapi/joi, and importing it with @hapi/joi. I've made the mistake of installing joiwithout the @hapi/prefix and it took me a while to find the error.

错误,您必须安装joinpm install @hapi/joi,并用其导入@hapi/joi。我犯了joi没有安装@hapi/前缀的错误,我花了一段时间才找到错误。

回答by Chavin Kwas

Just call "message()" function :

只需调用“message()”函数:

firstName: Joi.string().message("Your custom message")

回答by Siddharth Sunchu

The best solution I found was :

我发现的最佳解决方案是:

Create a Middleware for JOI validation

为 JOI 验证创建中间件

Validator.js - You can create your custom error object

Validator.js - 您可以创建自定义错误对象

const Joi = require('Joi');

module.exports = schema => (req, res, next) => {
  const result = Joi.validate(req.body, schema);
  if (result.error) {
    return res.status(422).json({
      errorCause: result.error.name,
      missingParams: result.error.details[0].path,
      message: result.error.details[0].message
    });
  }
  next();
};

In the routes or controller pass this middleware function

在路由或控制器中传递这个中间件功能


const joiValidator = require('../utils/validator'); // Wherever you have declare the validator or middlerware

   const  userSchema = joi.object().keys({
    email : joi.string().email().required(),
    password : joi.string().required()
  });

  routes.routes('/').get(joiValidator(userSchema), (req, res) => {
    res.status(200).send('Person Check');
  });