0%

gin表单验证struct tag

本文是对 validate tag not working in ShouldBindWith 的回答。

有人提了这么一个问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package main

import (
"log"
"net/http"

"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
)

// MyStruct ..
type MyStruct struct {
Order string `form:"order,default=DESC" validate:"omitempty,oneof=ASC DESC"`
}

func startPage(c *gin.Context) {
var person MyStruct
if c.ShouldBindWith(&person, binding.Query) == nil {
log.Println("====== Only Bind By Query String ======")
log.Println(person.Order)
c.String(http.StatusOK, "Success")
return
// log.Println(person.Address)
}
c.String(http.StatusBadRequest, "Failed")
return
}

func main() {

route := gin.Default()
route.Any("/testing", startPage)
route.Run(":8085")
}

然后表单验证的时候,明明 Order 传递了一个不符合 oneof=ASC DESC 的值,但却验证通过了。

原因

虽然 gin 使用了 go-playground/validator 来作为表单验证的组件,但是在 gin 里面却修改了 struct 验证的 tagname,我们可以看看 default_validator.go#L95

1
2
3
4
5
6
func (v *defaultValidator) lazyinit() {
v.once.Do(func() {
v.validate = validator.New()
v.validate.SetTagName("binding")
})
}

然后,我们就不能通过给 struct 加上 vaidate 的 tag 来写上我们的验证规则,取而代之的是,需要将我们的验证规则写在 binding 这个 tag 里面:

validate:"omitempty,oneof=ASC DESC" 替换成 binding:"omitempty,oneof=ASC DESC",我们即可实现在 gin 中使用 validator 验证我们的 struct。

1
2
3
type MyStruct struct {
Order string `form:"order,default=DESC" binding:"omitempty,oneof=ASC DESC"`
}

参考官方文档: 模型绑定和验证