Golang使用validator/v10如何自动校验切片内结构体字段
Go validator 嵌套切片自动校验实现方案
环境信息
- Golang版本:1.17.8
- 依赖版本:
github.com/go-playground/validator/v10
问题复现
待校验JSON载荷
{ "name": "Yomiko", "address": { "city": "Tokyo", "street": "Shibaura St" }, "children":[ { "lastName": "Takayashi" } ], "isEmployed": false }
初始结构体定义
package main type User struct { Name string Address *Address `validate:"required"` Children []*Child IsEmployed *bool `validate:"required"` } type Address struct { City string `validate:"required"` Street string `validate:"required"` } type Child struct { Title string `validate:"required"` FirstName string LastName string `validate:"required"` }
初始校验代码(不符合预期)
func TestUserPayload(t *testing.T) { actualUserPayload := NewUserPayloadFromFile("userpayload.json") validate := validator.New() err := validate.Struct(actualUserPayload) if err != nil { t.Error("Validation Error: ", err) } }
运行上述测试用例会直接通过,不会按预期抛出Child.Title字段缺失的required校验错误。只有手动遍历Children切片逐个校验内部元素时,才会触发预期报错,手动遍历的实现如下:
func TestUserPayload(t *testing.T) { actualUserPayload := NewUserPayloadFromFile("userpayload.json") validate := validator.New() err := validate.Struct(actualUserPayload) if err != nil { t.Error("Validation Error: ", err) } children := actualUserPayload.Children for _, child := range children { err := validate.Struct(child) if err != nil { t.Error("Validation Error: ", err) } } }
无需手动遍历的实现方式
validator 提供了dive校验标签,作用是告知校验器需要深入切片、数组、map这类集合类型的内部,对每个元素执行后续绑定的校验规则,不需要手动编写遍历逻辑。
只需要修改User结构体中Children字段的校验标签,加上dive规则即可:
type User struct { Name string Address *Address `validate:"required"` // 新增dive标签,自动校验切片内的每一个Child元素 Children []*Child `validate:"dive"` IsEmployed *bool `validate:"required"` }
修改完成后,直接调用validate.Struct(actualUserPayload)就会自动递归遍历Children切片下的所有元素,执行Child结构体上定义的所有字段校验规则,直接返回Child.Title字段缺失的校验错误。
扩展规则说明
- 如果要求Children切片本身不能为空,且每个元素都需要校验,可以将标签写为
validate:"required,dive" - 多层嵌套集合场景可以叠加使用dive,比如
[][]Child类型字段使用validate:"dive,dive"即可深入两层校验最内层的结构体 - map类型使用dive时默认校验value,如需同时校验key可在dive后追加keys相关规则
内容的提问来源于stack exchange,提问作者samme4life
相关产品推荐
相关产品推荐

