- Created by 郭强, last modified on Jul 14, 2022
gvalid
校验组件支持强大的递归校验(嵌套校验)特性。如果给定的校验数据中的属性或者键值为struct/map/slice
类型时,将会被自动执行递归校验。我们来看几个示例:
示例1,递归校验:struct
package main import ( "fmt" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gctx" ) type SearchReq struct { Key string `v:"required"` Option SearchOption } type SearchOption struct { Page int `v:"min:1"` Size int `v:"max:100"` } func main() { var ( ctx = gctx.New() req = SearchReq{ Key: "GoFrame", Option: SearchOption{ Page: 1, Size: 10000, }, } ) err := g.Validator().Data(req).Run(ctx) fmt.Println(err) }
执行后,终端输出:
The Size value `10000` must be equal or lesser than 100
示例2,递归校验:slice
package main import ( "fmt" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gctx" ) func main() { type Student struct { Name string `v:"required#Student Name is required"` Age int } type Teacher struct { Name string Students []Student } var ( ctx = gctx.New() teacher = Teacher{} data = g.Map{ "name": "john", "students": `[{"age":2},{"name":"jack", "age":4}]`, } ) err := g.Validator().Assoc(data).Data(teacher).Run(ctx) fmt.Println(err) }
执行后,终端输出:
Student Name is required
示例3,递归校验:map
package main import ( "fmt" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gctx" ) func main() { type Student struct { Name string `v:"required#Student Name is required"` Age int } type Teacher struct { Name string Students map[string]Student } var ( ctx = gctx.New() teacher = Teacher{ Name: "Smith", Students: map[string]Student{ "john": {Name: "", Age: 18}, }, } ) err := g.Validator().Data(teacher).Run(ctx) fmt.Println(err) }
执行后,终端输出:
Student Name is required
注意事项:空对象对递归校验的影响
package main import ( "fmt" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gctx" ) func main() { type Student struct { Name string `v:"required"` } type Teacher struct { Students Student } var ( ctx = gctx.New() teacher = Teacher{} data = g.Map{ "students": nil, } ) err := g.Validator().Assoc(data).Data(teacher).Run(ctx) fmt.Println(err) }
执行后,终端输出:
Student Name is required
有同学可能会觉得奇怪,明明我都没有传递Student
字段值,为什么还会递归校验Student
结构体里面的Name
字段?这是因为这里的 Student
属性是个空结构体,是带有默认值的(Name
默认值为空字符串)。递归校验里面,虽然 Student
不是必须参数,这个意思是你可以不传递,但是只要传递了就会按照里面属性的校验规则执行校验(带有默认值的空对象也算是有值)。可以对比和以下代码的差别:
package main import ( "fmt" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gctx" ) func main() { type Student struct { Name string `v:"required"` } type Teacher struct { Students *Student } var ( ctx = gctx.New() teacher = Teacher{} data = g.Map{ "students": nil, } ) err := g.Validator().Assoc(data).Data(teacher).Run(ctx) fmt.Println(err) }
和前一示例的唯一差异在于Student
属性从结构体改为了结构体指针*Student
,这样该属性不是空对象便没有默认值了。执行后,终端输出位空,表示校验通过。
Content Menu
- No labels
4 Comments
佳雨
这例子要写的这么复杂吗?直接一个二维数组不好吗?还搞个嵌套。一个批量将数据写数据库之前进行校验就好了,应该是大家用的最多的。
海亮
写嵌套的例子可以自行简化,而写简单的例子,则很难反过来。而且这里标题已经写着递归
jiuker
package main
import (
"fmt"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gctx"
)
func main() {
type Student struct {
Name string `v:"required#Student Name is required"`
Age int
}
type Teacher struct {
Name string
Students []*Student
}
var (
ctx = gctx.New()
teacher = Teacher{}
data = g.Map{
"name": "john",
"students": `[{"age":2},{"name":"jack", "age":4}]`,
}
)
err := g.Validator().Assoc(data).Data(teacher).Run(ctx)
fmt.Println(err)
}
当数据Slice递归的类型定义成 Students []*Student ,递归校验就失效了
yiiiple
package main
import (
"fmt"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gctx"
)
type SearchReq struct {
Key string `v:"required"`
Option *SearchOption
}
type SearchOption struct {
Page int `v:"min:1"`
Size int `v:"max:100"`
}
func main() {
var (
ctx = gctx.New()
req = SearchReq{
Key: "GoFrame",
Option: &SearchOption{
Page: 1,
Size: 10000,
},
}
)
err := g.Validator().Data(req).Run(ctx)
fmt.Println(err)
}
和楼上一样,当引用的struct定义为指针类型,就check失败了