在 Golang 中使用 OR 条件验证结构的两个字段

Validate two fields of struct with OR condition in Golang

我正在尝试验证具有两个字段的结构,其中一个是必需的,另一个不是。

这是结构:

type man struct {
    // required: true
    Numbers []int `json:"numbers"`
    // required: false
    Pass bool `json:"pass"`
}

为了验证我正在使用这个包:https://pkg.go.dev/gopkg.in/validator.v2

我的目标是创造以下条件:

数字为非零或传递为真。

但是,如果我将数字定义为非零值,它将阻止对 Pass 字段的检查。

我已尝试创建自定义验证器函数,但由于其中一个字段不是必需的,我不确定如何构建此条件。

谢谢!

type Man struct {
    // required: true
    Numbers []int `json:"numbers" cond1:"nonnil"`
    // required: false
    Pass bool `json:"pass" cond2:"nonzero"`
}

func main() {
    // .... 
    cond1Validator := validator.NewValidator()
    cond1Validator.SetTag("cond1")
    cond2Validator := validator.NewValidator()
    cond2Validator.SetTag("cond2")
    if errs := cond1Validator.Validate(man); errs != nil {
        if errs := cond2Validator.Validate(man); errs != nil {
            log.Fatalln(errs)
        }
    }
    // ....
}

您可以尝试自定义标签名称和多个验证器..

使用较新版本的验证程序包(例如 v9 以后),您可以使用 required_without 标签。

The field under validation must be present and not empty only when any of the other specified fields are not present. For strings ensures value is not "". For slices, maps, pointers, interfaces, channels and functions ensures the value is not nil.

type man struct {
    Numbers []int  `json:"numbers" validate:"required_without=Pass"`
    Pass    bool   `json:"pass"`
}

使用不同的输入进行测试:

man{}
man{nil, false}
man{nil, true}
man{[]int{}, false}

给出:

Key: 'man.Numbers' Error:Field validation for 'Numbers' failed on the 'required_without' tag
Key: 'man.Numbers' Error:Field validation for 'Numbers' failed on the 'required_without' tag
pass
pass

不幸的是,v2 您只能实现单字段验证,因此您实际上并没有一个很好且直接的方法来访问父结构。您可能必须将该结构包装在另一个结构中才能将 man 视为一个字段。

type wrapper struct {
    man man `validate:"man"`
}

// Very simple validation func
func manValidator(v interface{}, param string) error {
    m := v.(man)
    if m.Numbers != nil || m.Pass {
        return nil
    }
    return errors.New("validation failed")
}

func main() {
    validate.SetValidationFunc("man", manValidator)
    validator.Validate(wrapper{man{}})
}