我有这个代码:
package main
import (
"fmt"
"github.com/gin-gonic/gin"
)
type TestForm struct {
Age int `form:"age" binding:"required"`
Name string `form:"name" binding:"required"`
}
func home(c *gin.Context) {
c.HTML(200, "index.html", nil)
}
func homePost(c *gin.Context) {
var f TestForm
err := c.Bind(&f)
c.String(200, fmt.Sprintf("%v : %v", err, f))
}
func main() {
r := gin.Default()
r.LoadHTMLGlob("templates/*")
r.Use(gin.Recovery())
r.GET("/", home)
r.POST("/", homePost)
r.Run()
}
和 templates/index.html :
<!doctype html>
<html>
<head></head>
<body>
<h1>hello</h1>
<form action="/" method="POST">
<input type="text" name="name">
<input type="text" name="age">
<input type="submit">
</form>
</body>
</html>
当字段绑定(bind)/验证失败时,我想遍历所有字段以便在匹配字段上以 HTML 格式呈现错误。
如果我输入 test 作为 name
将 age
留空,响应是这样的:
Key: 'TestForm.Age' Error:Field validation for 'Age' failed on the 'required' tag : {0 asd}
我发现 err := c.Bind(&f)
返回的 err
是 validator.ValidationErrors
类型,它允许我要做到这一点,到目前为止一切都很好。
但是,如果我输入 test 作为 name
和 abc
作为 age`(或者 eve 只输入一个后面有空格的数字),响应是这样的:
strconv.ParseInt: parsing "abc": invalid syntax : {0 }
所以,这只是一个一般性错误,某处某处无法解析整数。
现在我无法知道哪个字段未通过验证,也无法获得有关其他未通过验证的字段的任何信息。有什么方法可以让 gin 告诉我 age
字段在这种情况下失败了吗?
最佳答案
我尝试过使用内置的 playground 验证来做到这一点,但没有成功。只是没有任何简单的方法来访问暴露给前端的实际字段名称。
因此,我采用了自定义验证方法。它更具可读性(前端 + 后端),特别是当您拥有自定义验证器时,这些验证器很难通过 playground 验证进行设置。您只需编写一次它们,然后基本上通过嵌入结构来重用验证器。
我在这里详细说明了如何使用它们的示例:More elegant way of validate body in go-gin
基本上,出于我在那篇文章中详述的原因,我总是使用模型(查询模型、人体模型等)。这使我可以轻松地向它们添加 Validate() 方法:
type User struct {
UserId string `form:"user_id"`
Name string `form:"name"`
}
func (user *User) Validate() errors.RestError {
if _, err := uuid.Parse(id); err != nil {
return errors.BadRequestError("user_id not a valid uuid")
}
return nil
}
重用示例:
type OtherUser struct {
User // embedded struct here
HasOther bool `form:"has_other"`
}
func (other *OtherUser) Validate() errors.RestError {
// extra validation goes here for example
return other.User.Validate()
}
关于validation - 如何从 Gin 绑定(bind)/验证中获取错误字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51920940/