英文:
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
我的目标是创建以下条件:
Numbers 不为零 或者 pass 为 true。
然而,如果我将 numbers 定义为非零,它将阻止对 Pass 字段的检查。
我尝试创建一个自定义的验证函数,但由于其中一个字段是可选的,我不确定如何构建这些条件。
谢谢!
英文:
I'm trying to validate a struct which has two fields, one of them is required and the other one is not.
This is the struct:
type man struct {
// required: true
Numbers []int `json:"numbers"`
// required: false
Pass bool `json:"pass"`
}
In order to validate I'm using this package: https://pkg.go.dev/gopkg.in/validator.v2
My goal is to create the below condition:
Numbers is nonzero OR pass is true.
However, if I define numbers as nonzero it will block the check of the Pass field.
I've tried to create a customized validator function, but since one of the fields is not required, I'm not sure how to build this conditions.
Thanks!
答案1
得分: 6
使用更新版本的validator包(例如v9
及更高版本),您可以使用required_without
标签。
在验证器中,当其他指定字段中没有任何一个存在时,被验证的字段必须存在且非空。对于字符串,确保值不是""。对于切片、映射、指针、接口、通道和函数,确保值不是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"`
}
// 非常简单的验证函数
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{}})
}
英文:
With more recent versions of the validator package (e.g. v9
onward) you can use required_without
tag.
> 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"`
}
Testing with different inputs:
man{}
man{nil, false}
man{nil, true}
man{[]int{}, false}
Gives:
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
<hr>
Unfortunately with v2
you can only implement single field validation, so you don't really have a nice and straightforward way to access the parent struct. You might have to wrap the struct in another struct to consider man
as a field.
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{}})
}
答案2
得分: 0
你可以尝试自定义标签名称和多个验证器。
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)
}
}
// ....
}
你可以尝试自定义标签名称和多个验证器。
英文:
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)
}
}
// ....
}
You can try custom tag name and multiple vaidators..
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论