从结构标记验证返回自定义错误消息



我正在使用Go 1.17和Gin,我想在将数据发送到数据库之前实现结构验证。我从杜松子酒文档中取了一个例子。

在结构中,我们可以声明不同的标签来验证这样的字段:

type User struct {
FirstName      string `json:"first_name" binding:"required"`
LastName       string `json:"last_name" binding:"required"`
Age            uint8  `json:"age" binding:"gte=0,lte=130"`
Email          string `json:"email" binding:"required,email"`
FavouriteColor string `json:"favourite_color" binding:"iscolor"`
}

在处理程序中,我可以获取这样的错误:

var u User
if err := c.ShouldBindWith(&u, binding.Query); err == nil {
c.JSON(http.StatusOK, gin.H{"message": "Good Job"})
} else {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
}

错误消息为:

{
"error": "Key: 'User.FirstName' Error:Field validation for 'FirstName' failed on the 'required' tagnKey: 'User.LastName' Error:Field validation for 'LastName' failed on the 'required' tagnKey: 'User.Email' Error:Field validation for 'Email' failed on the 'required' tagnKey: 'User.FavouriteColor' Error:Field validation for 'FavouriteColor' failed on the 'iscolor' tag"
}

错误消息太过冗长——如何向用户返回更好的错误?我想将json响应建模为:

{
"errors": [
"first_name": "This field is required",
"last_name": "This field is required",
"age": "This field is required",
"email": "Invalid email"
]
}

Gin-gonic使用包github.com/go-playground/validator/v10执行绑定验证。如果验证失败,则返回的错误为validator.ValidationErrors

这一点没有明确提及,但在模型绑定和验证中,它指出:

Gin使用go操场/验证器/v10进行验证。在这里查看关于标签使用的完整文档。

链接到go-playground/validator/v10文档,您可以在其中找到段落Validation Functions Return Type错误。

您可以使用标准的errors包来检查错误是否为,打开包装,然后访问单个字段,即validator.FieldError。由此,您可以构建任何您想要的错误消息。

给定这样的错误模型:

type ApiError struct {
Field string
Msg   string
}

你可以这样做:

var u User
err := c.BindQuery(&u);
if err != nil {
var ve validator.ValidationErrors
if errors.As(err, &ve) {
out := make([]ApiError, len(ve))
for i, fe := range ve {
out[i] = ApiError{fe.Field(), msgForTag(fe.Tag())}
}
c.JSON(http.StatusBadRequest, gin.H{"errors": out})
}
return
}

带有助手功能,可以为您的验证规则输出自定义错误消息:

func msgForTag(tag string) string {
switch tag {
case "required":
return "This field is required"
case "email":
return "Invalid email"
}
return ""
}

在我的测试中,这个输出:

{
"errors": [
{
"Field": "Number",
"Msg": "This field is required"
}
]
}

PS:要获得带有动态键的json输出,可以使用map[string]string而不是固定的结构模型。

相关内容

  • 没有找到相关文章

最新更新