【问题标题】:Joi validation error from which field to show error next to it in UI来自哪个字段的 Joi 验证错误在 UI 中在其旁边显示错误
【发布时间】:2020-05-18 06:58:14
【问题描述】:

我必须使用 Joi 验证库来验证 API 输入并发送输出。

我说过创建了如下模式:

import Joi from '@hapi/joi'

const eventSchema = Joi.object({
  title: Joi.string()
    .min(7)
    .max(50)
    .required()
    .error(() => Error('Event title has to be least 7 and max 50 characters.')),

  description: Joi.string()
    .min(10)
    .max(400)
    .required()
    .error(() => Error('Event description has to be least 10 and max 400 characters.')),

  place: Joi.string()
    .min(6)
    .max(40)
    .required()
    .error(() => Error('Event place has to be least 6 and max 40 characters.'))
})
export default eventSchema

当我验证这个时,我得到了预期的验证错误。这里的问题是我不知道哪个字段真正导致了错误。我想知道这一点,因为我想准确地在导致错误的字段旁边显示错误,而不是在表单顶部显示通用验证消息。

const isValid = eventSchema.validate()

if (isValid.error) {
  const fieldNameWhichCauseError = ???

  return {
   errors: { [fieldNameWhichCauseError]: isValid.error.message }
  }
}

// Everything looks good save to db
// ...etc.

上面的代码现在可以知道 fieldNameWhichCauseError = ??? 中的字段名称。有人能帮帮我吗?我还没有看到有人做这样的场景。我也没有在文档中找到。我有很多架构和验证,这确实阻碍了我在 UI 中的适当位置显示错误。

【问题讨论】:

    标签: javascript node.js hapijs joi


    【解决方案1】:

    我自己想通了。有一天它可能会帮助有人在这里搜索。

    首先我会创建一个自定义的 ValidationError 对象。

    class ValidationError extends Error {
       constructor(message, fieldName) {
         super(message)
         this.fieldName = fieldName
       }
    }
    

    现在在问题中发布的上述代码中使用此类。使用 ValidationError 而不是 Error 类,并将字段名称传递给它。示例

    const eventSchema = Joi.object({
      title: Joi.string()
        .min(7)
        .max(50)
        .required()
        .error(() => new ValidationError('Event title has to be least 7 and max 50 characters.', 'title'))
    })
    

    记得在使用自定义类时使用new。验证的代码可以从传下来的错误对象中获取error.fieldName值。

    我希望这是正确的方法。如果有更好的方法,请发布我会接受它作为答案。

    【讨论】:

      【解决方案2】:

      我认为有更好的方法来实现这一点,因为不推荐使用抛出错误来实现这一点。 (https://github.com/hapijs/joi/blob/master/API.md#anyerrorerr)

      您应该利用any.messages (https://github.com/hapijs/joi/blob/master/API.md#anymessagesmessages) 并添加您的自定义消息。按照您定义它们的方式,即使用户没有指定任何内容,您也总是会收到相同类型的错误消息。还使用错误覆盖abortEarly 选项。这意味着您不会收到所有消息,只会收到第一条消息。

      可以像这样使用消息。

      const Joi = require('@hapi/joi');
      const eventSchema = Joi.object({
          title: Joi.string()
              .min(7)
              .max(50)
              .required()
              .messages({
                  'string.base': `"description" should be a type of 'text'`,
                  'string.min': '"title" has to be least {#limit} characters.',
                  'string.max': '"title" has to be max {#limit} characters.',
                  'any.required': `"title" is a required field`,
              }),
      
          description: Joi.string()
              .min(10)
              .max(400)
              .required()
              .messages({
                  'string.base': `"description" should be a type of 'text'`,
                  'string.min': '"description" has to be least {#limit} characters.',
                  'string.max': '"description" has to be max {#limit} characters.',
                  'any.required': `"description" is a required field`
              }),
      
          place: Joi.string()
              .min(6)
              .max(40)
              .required()
              .messages({
                  'string.base': `"place" should be a type of 'text'`,
                  'string.min': '"place" has to be least {#limit} characters.',
                  'string.max': '"place" has to be max {#limit} characters.',
                  'any.required': `"place" is a required field`
              })
      });
      
      eventSchema.validate({
          "title": "hi"
      }, {
          "abortEarly": false
      });
      
      

      【讨论】:

      • 这是个好建议。你看它仍然没有给出导致错误的字段的答案,所以在某种程度上我仍然会遇到同样的问题
      【解决方案3】:

      在 Joi 17.4 上,validate() 返回的 error 有一个名为 details 的属性,您可以从中访问有关这些错误的详细信息(例如这些错误属于哪些字段) .

      【讨论】:

        猜你喜欢
        • 2012-02-17
        • 2014-10-30
        • 2012-06-29
        • 1970-01-01
        • 2012-06-12
        • 2013-02-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多