如何使用验证器 v10 验证 null.v4 包类型的结构字段?
how to validate a struct field of type null.v4 package with validator v10?
我有一个结构,我正在尝试使用验证器 v10 验证一个结构,该结构的字段可以是来自 null.v4 包的 null.XX 类型。
type FooStruct struct {
Foo null.Int `json:"foo" binding:"nullIntMin=1"`
}
它(显然)不是开箱即用的,所以我正在尝试制作一个自定义验证器。
var validateNullIntMin validator.Func = func(fl validator.FieldLevel) bool {
number, ok := fl.Field().Interface().(null.Int)
min := cToInt(fl.Param())
if ok {
if number.Value > min && number.Valid {
return false
}
}
return true
}
func cToInt(param string) int64 {
i, err := strconv.ParseInt(param, 0, 64)
panic(err)
return i
}
问题是数据从未经过验证。甚至从未进入函数,我不明白为什么。
重现示例:
package main
import (
"log"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
"github.com/go-playground/validator"
"gopkg.in/guregu/null.v4"
)
type FooStruct struct {
Foo null.Int `json:"foo" binding:"nullIntMin=3"`
}
var validateNullIntMin validator.Func = func(fl validator.FieldLevel) bool {
log.Println("inside validator")
number, ok := fl.Field().Interface().(null.Int)
min := cToInt(fl.Param())
if ok {
if number.Valid && number.Int64 > min {
return false
}
}
return true
}
func cToInt(param string) int64 {
i, err := strconv.ParseInt(param, 0, 64)
panic(err)
return i
}
func main() {
route := gin.Default()
// Custom validator
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
v.RegisterValidation("nullIntMin", validateNullIntMin)
}
route.POST("/foo", postFoo)
route.Run(":5000")
}
func postFoo(c *gin.Context) {
var f FooStruct
err := c.BindJSON(&f)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"status": http.StatusText(http.StatusBadRequest)})
return
}
c.JSON(http.StatusOK, gin.H{"status": http.StatusText(http.StatusOK), "data": f.Foo.Int64})
}
如果你用
调用它
{"foo":1}
你会得到{
“数据”:1,
“状态”:“好的”
}
当我期待 Error:Field validation for 'Foo' failed on the 'nullIntMin' tag
您不需要在验证器中解析字段并为特殊类型创建自定义案例。
相反,只需创建一个新类型,然后您就可以使用普通绑定。
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
v.RegisterCustomTypeFunc(nullIntValidator, null.Int{})
}
func nullIntValidator(field reflect.Value) interface{} {
if valuer, ok := field.Interface().(null.Int); ok {
if valuer.Valid {
return valuer.Int64
}
}
return nil
}
type FooStruct struct {
Foo null.Int `json:"foo" binding:"min=3"`
}
我有一个结构,我正在尝试使用验证器 v10 验证一个结构,该结构的字段可以是来自 null.v4 包的 null.XX 类型。
type FooStruct struct {
Foo null.Int `json:"foo" binding:"nullIntMin=1"`
}
它(显然)不是开箱即用的,所以我正在尝试制作一个自定义验证器。
var validateNullIntMin validator.Func = func(fl validator.FieldLevel) bool {
number, ok := fl.Field().Interface().(null.Int)
min := cToInt(fl.Param())
if ok {
if number.Value > min && number.Valid {
return false
}
}
return true
}
func cToInt(param string) int64 {
i, err := strconv.ParseInt(param, 0, 64)
panic(err)
return i
}
问题是数据从未经过验证。甚至从未进入函数,我不明白为什么。
重现示例:
package main
import (
"log"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
"github.com/go-playground/validator"
"gopkg.in/guregu/null.v4"
)
type FooStruct struct {
Foo null.Int `json:"foo" binding:"nullIntMin=3"`
}
var validateNullIntMin validator.Func = func(fl validator.FieldLevel) bool {
log.Println("inside validator")
number, ok := fl.Field().Interface().(null.Int)
min := cToInt(fl.Param())
if ok {
if number.Valid && number.Int64 > min {
return false
}
}
return true
}
func cToInt(param string) int64 {
i, err := strconv.ParseInt(param, 0, 64)
panic(err)
return i
}
func main() {
route := gin.Default()
// Custom validator
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
v.RegisterValidation("nullIntMin", validateNullIntMin)
}
route.POST("/foo", postFoo)
route.Run(":5000")
}
func postFoo(c *gin.Context) {
var f FooStruct
err := c.BindJSON(&f)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"status": http.StatusText(http.StatusBadRequest)})
return
}
c.JSON(http.StatusOK, gin.H{"status": http.StatusText(http.StatusOK), "data": f.Foo.Int64})
}
如果你用
调用它{"foo":1}
你会得到{ “数据”:1, “状态”:“好的” }
当我期待 Error:Field validation for 'Foo' failed on the 'nullIntMin' tag
您不需要在验证器中解析字段并为特殊类型创建自定义案例。
相反,只需创建一个新类型,然后您就可以使用普通绑定。
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
v.RegisterCustomTypeFunc(nullIntValidator, null.Int{})
}
func nullIntValidator(field reflect.Value) interface{} {
if valuer, ok := field.Interface().(null.Int); ok {
if valuer.Valid {
return valuer.Int64
}
}
return nil
}
type FooStruct struct {
Foo null.Int `json:"foo" binding:"min=3"`
}