在 Joi 中返回多个错误

Joe*_*sen 4 node.js express hapijs joi

我正在尝试从我的 Joi 验证模式返回多个自定义错误消息。这是架构

const Joi = require("@hapi/joi");
const string = Joi.string();
const emailSchema = string.email();
const usernameSchema = string
  .min(3)
  .max(30)
  .error(() => "Username must be between 3 and 30 characters");
const passwordSchema = string
  .min(6)
  .error(() => "Password must be at least 6 characters");
const confirmPasswordSchema = Joi.valid(Joi.ref("passwordSchema")).error(
  () => "Passwords must match"
);

const localRegistrationSchema = Joi.object().keys({
  email: emailSchema.required().error(() => "Email is required"),
  username: usernameSchema.required().error(() => "Username is required"),
  password: passwordSchema.required().error(() => "Password is required"),
  confirmPassword: confirmPasswordSchema
});
Run Code Online (Sandbox Code Playgroud)

这是我使用架构的地方

const { error } = localRegistrationSchema.validate(req.body, {
        abortEarly: false
      });
console.log(error);
if (error) throw Boom.boomify(error);
Run Code Online (Sandbox Code Playgroud)

但我不断收到 TypeError: Cannot read property 'filter' of undefined 这看起来是由

details.push({
    message,
    path: item.path.filter((v) => typeof v !== 'object'),
    type: item.code,
    context: item.local
});
Run Code Online (Sandbox Code Playgroud)

这是 Joi 错误处理代码的一部分

当我不附加 .error() 部分时,我没有收到此错误,但如果我使用 .error(new Error("custom error message"),则无法显示多个错误

我无法弄清楚出了什么问题,并且无法通过任何其他方式返回多个自定义错误消息

a13*_*300 6

错误

我调试了您的代码,只是返回() => 'some error message'不适用于您的解决方案。我们需要返回一个函数。您收到错误,因为path自定义错误消息中的属性是undefined.

在此处输入图片说明


错误链接不起作用

const schema = Joi.object({
  prop: Joi.string()
           .min(9)
           .error(() => 'min error message')
           .required()
           .error(() => 'required error message');
});
Run Code Online (Sandbox Code Playgroud)

只有一个切换的错误消息有效

const schema = Joi.object({
  username: Joi.string()
            .min(9)
            .required()
            .error((errors) => {
              for (err of errors) {
                switch (err.code) {
                  case ('string.min'): {
                    return simpleErrorMsgFunc("prop min error message", ["prop"])(); // invoke
                  }
                  case 'any.required': {
                    return simpleErrorMsgFunc("prop is required", ["prop"])(); // invoke
                  }
                  default: {
                    return simpleErrorMsgFunc("prop has error", ["prop"])(); // invoke
                  }
                }
              }
            }),
});
Run Code Online (Sandbox Code Playgroud)


辅助功能

我的解决方案的核心是以下功能。它返回一个function返回自定义错误object。:

function simpleErrorMsgFunc(message, path) {
  return () => {
    return {
      toString: () => message,
      message,
      path,
    }
  };
}
Run Code Online (Sandbox Code Playgroud)


整体解决方案

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

function simpleErrorMsgFunc(message, path) {
  return () => {
    return {
      toString: () => message,
      message,
      path,
    }
  };
}

const localRegistrationSchema = Joi.object().keys({
  // email is simple, we only need 1 error message
  email: Joi.string()
            .email()
            .required()
            .error(simpleErrorMsgFunc("Email is required", ["email"])),

  // username is advanced, we need 2 error message
  username: Joi.string()
            .min(3)
            .max(30)
            .required()
            .error((errors) => {
              for (err of errors) {
                switch (err.code) {
                  case ('string.min' || 'string.max'): {
                    return simpleErrorMsgFunc("username must be between 3 and 30 characters", ["username"])(); // invoke
                  }
                  case 'any.required': {
                    return simpleErrorMsgFunc("username is required", ["username"])(); // invoke
                  }
                  default: {
                    return simpleErrorMsgFunc("username has error", ["username"])(); // invoke
                  }
                }
              }
            }),

// password is advanced, we need 2 error message
  password: Joi.string()
               .min(6)
               .required()
               .error((errors) => {
                for (err of errors) {
                  switch (err.code) {
                    case ('string.min'): {
                      return simpleErrorMsgFunc("Password must be at least 6 characters", ["password"])(); // invoke
                    }
                    case 'any.required': {
                      return simpleErrorMsgFunc("Password is required", ["password"])(); // invoke
                    }
                    default: {
                      return simpleErrorMsgFunc("password has error", ["password"])(); // invoke
                    }
                  }
                }
              }),

  confirmPassword: Joi.valid(Joi.ref("password"))
                     .error(simpleErrorMsgFunc("Passwords must match", ['confirmPassword']))
});

const req = {
  body: {
    email: 'some@gmail.com',
    username: 'hee',
     password: '45645656',
     confirmPassword: '45645656_',
  },
};

const { error } = localRegistrationSchema.validate(req.body, {
  abortEarly: false
});
console.log(JSON.stringify(error, null, 2));
Run Code Online (Sandbox Code Playgroud)

PS 我注意到您的confirmPassword财产不是必需的!