首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用自定义验证器验证结构数据类型?

如何使用自定义验证器验证结构数据类型?
EN

Stack Overflow用户
提问于 2021-04-26 21:16:02
回答 2查看 4.7K关注 0票数 6

我正在使用go-playground/validator/v10来验证一些输入,并且在定制的验证标记和函数方面遇到了一些问题。问题是,当一个struct字段是不同的结构时,函数就不会被调用。这就是一个例子:

代码语言:javascript
复制
type ChildStruct struct {
    Value int
}

type ParentStruct struct {
    Child ChildStruct `validate:"myValidate"`
}

func myValidate(fl validator.FieldLevel) bool {
    fmt.Println("INSIDE MY VALIDATOR") // <- This is never printed
    return false
}

func main() {
    validator := validator.New()
    validator.RegisterValidation("myValidate", myValidate)
    data := &ParentStruct{
        Child: ChildStruct{
            Value: 10,
        },
    }
    validateErr := validator.Struct(data)
    if validateErr != nil { // <- This is always nil since MyValidate is never called
        fmt.Println("GOT ERROR")
        fmt.Println(validateErr)
    }
    fmt.Println("DONE")
}

如果我将parentStruct更改为:

代码语言:javascript
复制
type ParentStruct struct {
    Child int `validate:"myValidate"`
}

一切都正常。但是,如果我将validate:"myValidate"部件添加到ChildStruct中也是有效的,那么返回的错误是当它应该说ParentStruct.Child是错误的时候,ChildStruct.Value是错误的。

有人知道我做错了什么吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-05-03 17:23:56

在搜索了一段时间之后,我终于找到了一个名为RegisterCustomTypeFunc的函数,它注册了一个自定义类型,这将使go-playground/validator/v10能够验证它。因此,解决方案是在问题中的示例中添加以下内容:

代码语言:javascript
复制
func childStructCustomTypeFunc(field reflect.Value) interface{} {   
    if value, ok := field.Interface().(ChildStruct); ok {
        return value.Value
    }
    return nil
}

连同:

代码语言:javascript
复制
validator.RegisterCustomTypeFunc(childStructCustomTypeFunc, ChildStruct{})

现在,验证器将进入myValidate函数,返回消息将是ParentStruct.Child字段的一个错误。

票数 5
EN

Stack Overflow用户

发布于 2021-04-26 23:38:36

函数validator.RegisterValidation(...)正在注册一个字段级别的自定义验证器,注册函数的类型表示func(fl validator.FieldLevel) bool

Struct字段本身不会以这种方式进行验证,并且您的自定义验证程序将被忽略。

要验证一个struct字段,应该使用validate.RegisterStructValidation(myValidate, ChildStruct{}),其中函数myValidate的类型为validator.StructLevelFunc

在此函数中,您可以对结构执行验证,可以是字段本身和/或其嵌套字段:

代码语言:javascript
复制
func myValidate(sl validator.StructLevel) {
    fmt.Println("INSIDE MY VALIDATOR") // now called
    if sl.Current().Interface().(ChildStruct).Value != 20 {
        sl.ReportError(sl.Current().Interface(), "ChildStruct", "", "", "")
    }
}

func main() {
    vald := validator.New()
    vald.RegisterStructValidation(myValidate, ChildStruct{})
    data := &ParentStruct{
        Child: ChildStruct{
            Value: 10,
        },
    }
    validateErr := vald.Struct(data)
    if validateErr != nil {         
        fmt.Println("GOT ERROR")
        fmt.Println(validateErr)
    }
    fmt.Println("DONE")
}

操场上的例子:https://play.golang.org/p/f0f2YE_e1VL

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67273914

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档