mirror of
https://gitee.com/johng/gf
synced 2026-07-08 14:39:50 +08:00
improve struct validation for package gvalid
This commit is contained in:
@ -82,24 +82,27 @@ func (r *Request) doParse(pointer interface{}, requestType int) error {
|
||||
// 1. {"id":1, "name":"john"}
|
||||
// 2. ?id=1&name=john
|
||||
case reflect.Ptr, reflect.Struct:
|
||||
var (
|
||||
err error
|
||||
data map[string]interface{}
|
||||
)
|
||||
// Converting.
|
||||
switch requestType {
|
||||
case parseTypeQuery:
|
||||
if err := r.GetQueryStruct(pointer); err != nil {
|
||||
if data, err = r.doGetQueryStruct(pointer); err != nil {
|
||||
return err
|
||||
}
|
||||
case parseTypeForm:
|
||||
if err := r.GetFormStruct(pointer); err != nil {
|
||||
if data, err = r.doGetFormStruct(pointer); err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
if err := r.GetStruct(pointer); err != nil {
|
||||
if data, err = r.doGetRequestStruct(pointer); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Validation.
|
||||
if err := gvalid.CheckStruct(pointer, nil); err != nil {
|
||||
if err := gvalid.CheckStructWithParamMap(pointer, data, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -107,7 +110,7 @@ func (r *Request) doParse(pointer interface{}, requestType int) error {
|
||||
// [{"id":1, "name":"john"}, {"id":, "name":"smith"}]
|
||||
case reflect.Array, reflect.Slice:
|
||||
// If struct slice conversion, it might post JSON/XML content,
|
||||
// so it uses gjson for the conversion.
|
||||
// so it uses `gjson` for the conversion.
|
||||
j, err := gjson.LoadContent(r.GetBody())
|
||||
if err != nil {
|
||||
return err
|
||||
@ -116,7 +119,11 @@ func (r *Request) doParse(pointer interface{}, requestType int) error {
|
||||
return err
|
||||
}
|
||||
for i := 0; i < reflectVal2.Len(); i++ {
|
||||
if err := gvalid.CheckStruct(reflectVal2.Index(i), nil); err != nil {
|
||||
if err := gvalid.CheckStructWithParamMap(
|
||||
reflectVal2.Index(i),
|
||||
j.GetMap(gconv.String(i)),
|
||||
nil,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@ -188,13 +188,18 @@ func (r *Request) GetFormMapStrVar(kvMap ...map[string]interface{}) map[string]*
|
||||
// given struct object. Note that the parameter <pointer> is a pointer to the struct object.
|
||||
// The optional parameter <mapping> is used to specify the key to attribute mapping.
|
||||
func (r *Request) GetFormStruct(pointer interface{}, mapping ...map[string]string) error {
|
||||
_, err := r.doGetFormStruct(pointer, mapping...)
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *Request) doGetFormStruct(pointer interface{}, mapping ...map[string]string) (data map[string]interface{}, err error) {
|
||||
r.parseForm()
|
||||
data := r.formMap
|
||||
data = r.formMap
|
||||
if data == nil {
|
||||
data = map[string]interface{}{}
|
||||
}
|
||||
if err := r.mergeDefaultStructValue(data, pointer); err != nil {
|
||||
return nil
|
||||
return data, nil
|
||||
}
|
||||
return gconv.Struct(data, pointer, mapping...)
|
||||
return data, gconv.Struct(data, pointer, mapping...)
|
||||
}
|
||||
|
||||
@ -196,13 +196,18 @@ func (r *Request) GetQueryMapStrVar(kvMap ...map[string]interface{}) map[string]
|
||||
// to the struct object. The optional parameter <mapping> is used to specify the key to
|
||||
// attribute mapping.
|
||||
func (r *Request) GetQueryStruct(pointer interface{}, mapping ...map[string]string) error {
|
||||
_, err := r.doGetQueryStruct(pointer, mapping...)
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *Request) doGetQueryStruct(pointer interface{}, mapping ...map[string]string) (data map[string]interface{}, err error) {
|
||||
r.parseQuery()
|
||||
data := r.GetQueryMap()
|
||||
data = r.GetQueryMap()
|
||||
if data == nil {
|
||||
data = map[string]interface{}{}
|
||||
}
|
||||
if err := r.mergeDefaultStructValue(data, pointer); err != nil {
|
||||
return nil
|
||||
return data, nil
|
||||
}
|
||||
return gconv.Struct(data, pointer, mapping...)
|
||||
return data, gconv.Struct(data, pointer, mapping...)
|
||||
}
|
||||
|
||||
@ -270,14 +270,19 @@ func (r *Request) GetRequestMapStrVar(kvMap ...map[string]interface{}) map[strin
|
||||
// the parameter <pointer> is a pointer to the struct object.
|
||||
// The optional parameter <mapping> is used to specify the key to attribute mapping.
|
||||
func (r *Request) GetRequestStruct(pointer interface{}, mapping ...map[string]string) error {
|
||||
data := r.GetRequestMap()
|
||||
_, err := r.doGetRequestStruct(pointer, mapping...)
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *Request) doGetRequestStruct(pointer interface{}, mapping ...map[string]string) (data map[string]interface{}, err error) {
|
||||
data = r.GetRequestMap()
|
||||
if data == nil {
|
||||
data = map[string]interface{}{}
|
||||
}
|
||||
if err := r.mergeDefaultStructValue(data, pointer); err != nil {
|
||||
return nil
|
||||
return data, nil
|
||||
}
|
||||
return gconv.Struct(data, pointer, mapping...)
|
||||
return data, gconv.Struct(data, pointer, mapping...)
|
||||
}
|
||||
|
||||
// mergeDefaultStructValue merges the request parameters with default values from struct tag definition.
|
||||
|
||||
@ -23,7 +23,7 @@ func Test_Params_Json_Request(t *testing.T) {
|
||||
Name string
|
||||
Time *time.Time
|
||||
Pass1 string `p:"password1"`
|
||||
Pass2 string `p:"password2" v:"required|length:2,20|password3|same:password1#||密码强度不足|两次密码不一致"`
|
||||
Pass2 string `p:"password2" v:"password2@required|length:2,20|password3|same:password1#||密码强度不足|两次密码不一致"`
|
||||
}
|
||||
p, _ := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
|
||||
@ -395,7 +395,7 @@ func Test_Params_Struct(t *testing.T) {
|
||||
Name string
|
||||
Time *time.Time
|
||||
Pass1 string `p:"password1"`
|
||||
Pass2 string `p:"password2" v:"passwd1 @required|length:2,20|password3#||密码强度不足"`
|
||||
Pass2 string `p:"password2" v:"password2 @required|length:2,20|password3#||密码强度不足"`
|
||||
}
|
||||
p, _ := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
@ -452,8 +452,8 @@ func Test_Params_Struct(t *testing.T) {
|
||||
t.Assert(client.PostContent("/struct1", `id=1&name=john&password1=123&password2=456`), `1john123456`)
|
||||
t.Assert(client.PostContent("/struct2", `id=1&name=john&password1=123&password2=456`), `1john123456`)
|
||||
t.Assert(client.PostContent("/struct2", ``), ``)
|
||||
t.Assert(client.PostContent("/struct-valid", `id=1&name=john&password1=123&password2=0`), `The passwd1 value length must be between 2 and 20; 密码强度不足`)
|
||||
t.Assert(client.PostContent("/parse", `id=1&name=john&password1=123&password2=0`), `The passwd1 value length must be between 2 and 20; 密码强度不足`)
|
||||
t.Assert(client.PostContent("/struct-valid", `id=1&name=john&password1=123&password2=0`), `The password2 value length must be between 2 and 20; 密码强度不足`)
|
||||
t.Assert(client.PostContent("/parse", `id=1&name=john&password1=123&password2=0`), `The password2 value length must be between 2 and 20; 密码强度不足`)
|
||||
t.Assert(client.PostContent("/parse", `{"id":1,"name":"john","password1":"123Abc!@#","password2":"123Abc!@#"}`), `1john123Abc!@#123Abc!@#`)
|
||||
})
|
||||
}
|
||||
@ -464,7 +464,7 @@ func Test_Params_Structs(t *testing.T) {
|
||||
Name string
|
||||
Time *time.Time
|
||||
Pass1 string `p:"password1"`
|
||||
Pass2 string `p:"password2" v:"passwd1 @required|length:2,20|password3#||密码强度不足"`
|
||||
Pass2 string `p:"password2" v:"password2 @required|length:2,20|password3#||密码强度不足"`
|
||||
}
|
||||
p, _ := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
@ -491,3 +491,39 @@ func Test_Params_Structs(t *testing.T) {
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Params_Struct_Validation(t *testing.T) {
|
||||
type User struct {
|
||||
Id int `v:"required"`
|
||||
Name string `v:"name@required-with:id"`
|
||||
}
|
||||
p, _ := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
s.Group("/", func(group *ghttp.RouterGroup) {
|
||||
group.ALL("/", func(r *ghttp.Request) {
|
||||
var (
|
||||
err error
|
||||
user *User
|
||||
)
|
||||
err = r.Parse(&user)
|
||||
if err != nil {
|
||||
r.Response.WriteExit(err)
|
||||
}
|
||||
r.Response.WriteExit(user.Id, user.Name)
|
||||
})
|
||||
})
|
||||
s.SetPort(p)
|
||||
s.SetDumpRouterMap(false)
|
||||
s.Start()
|
||||
defer s.Shutdown()
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
c := g.Client()
|
||||
c.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", p))
|
||||
t.Assert(c.GetContent("/", ``), `The Id field is required`)
|
||||
t.Assert(c.GetContent("/", `id=1&name=john`), `1john`)
|
||||
t.Assert(c.PostContent("/", `id=1&name=john&password1=123&password2=456`), `1john`)
|
||||
t.Assert(c.PostContent("/", `id=1`), `The name field is required`)
|
||||
})
|
||||
}
|
||||
|
||||
@ -22,7 +22,7 @@ func Test_Params_Xml_Request(t *testing.T) {
|
||||
Name string
|
||||
Time *time.Time
|
||||
Pass1 string `p:"password1"`
|
||||
Pass2 string `p:"password2" v:"required|length:2,20|password3|same:password1#||密码强度不足|两次密码不一致"`
|
||||
Pass2 string `p:"password2" v:"password2@required|length:2,20|password3|same:password1#||密码强度不足|两次密码不一致"`
|
||||
}
|
||||
p, _ := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
|
||||
@ -14,6 +14,7 @@ import (
|
||||
"github.com/gogf/gf/os/gtime"
|
||||
"github.com/gogf/gf/text/gregex"
|
||||
"github.com/gogf/gf/util/gconv"
|
||||
"github.com/gogf/gf/util/gutil"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@ -232,8 +233,9 @@ func (v *Validator) doCheckBuildInRules(
|
||||
|
||||
// Values of two fields should be equal as string.
|
||||
case "same":
|
||||
if v, ok := dataMap[rulePattern]; ok {
|
||||
if strings.Compare(valueStr, gconv.String(v)) == 0 {
|
||||
_, foundValue := gutil.MapPossibleItemByKey(dataMap, rulePattern)
|
||||
if foundValue != nil {
|
||||
if strings.Compare(valueStr, gconv.String(foundValue)) == 0 {
|
||||
match = true
|
||||
}
|
||||
}
|
||||
@ -247,8 +249,9 @@ func (v *Validator) doCheckBuildInRules(
|
||||
// Values of two fields should not be equal as string.
|
||||
case "different":
|
||||
match = true
|
||||
if v, ok := dataMap[rulePattern]; ok {
|
||||
if strings.Compare(valueStr, gconv.String(v)) == 0 {
|
||||
_, foundValue := gutil.MapPossibleItemByKey(dataMap, rulePattern)
|
||||
if foundValue != nil {
|
||||
if strings.Compare(valueStr, gconv.String(foundValue)) == 0 {
|
||||
match = false
|
||||
}
|
||||
}
|
||||
@ -302,6 +305,7 @@ func (v *Validator) doCheckBuildInRules(
|
||||
// 16x, 19x
|
||||
case "phone":
|
||||
match = gregex.IsMatchString(`^13[\d]{9}$|^14[5,7]{1}\d{8}$|^15[^4]{1}\d{8}$|^16[\d]{9}$|^17[0,2,3,5,6,7,8]{1}\d{8}$|^18[\d]{9}$|^19[\d]{9}$`, valueStr)
|
||||
|
||||
// Loose mobile phone number verification(宽松的手机号验证)
|
||||
// As long as the 11 digit numbers beginning with
|
||||
// 13, 14, 15, 16, 17, 18, 19 can pass the verification (只要满足 13、14、15、16、17、18、19开头的11位数字都可以通过验证)
|
||||
|
||||
@ -9,17 +9,18 @@ package gvalid
|
||||
import (
|
||||
"github.com/gogf/gf/internal/structs"
|
||||
"github.com/gogf/gf/util/gconv"
|
||||
"github.com/gogf/gf/util/gutil"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// doCheckStructWithParamMapInput is used for struct validation for internal function.
|
||||
type doCheckStructWithParamMapInput struct {
|
||||
Object interface{} // Can be type of struct/*struct.
|
||||
ParamMap interface{} // Validation parameter map. Note that it acts different according attribute `ParamMapStrict`.
|
||||
ParamMapStrict bool // Strictly using `ParamMap` as its validation source. If false, it ignores `ParamMap` and retrieves values from `Object`.
|
||||
CustomRules interface{} // Custom validation rules.
|
||||
CustomErrorMessageMap CustomMsg // Custom error message map for validation rules.
|
||||
Object interface{} // Can be type of struct/*struct.
|
||||
ParamMap interface{} // Validation parameter map. Note that it acts different according attribute `UseParamMapInsteadOfObjectValue`.
|
||||
UseParamMapInsteadOfObjectValue bool // Using `ParamMap` as its validation source instead of values from `Object`.
|
||||
CustomRules interface{} // Custom validation rules.
|
||||
CustomErrorMessageMap CustomMsg // Custom error message map for validation rules.
|
||||
}
|
||||
|
||||
var (
|
||||
@ -39,11 +40,11 @@ func (v *Validator) CheckStruct(object interface{}, customRules interface{}, cus
|
||||
message = customErrorMessageMap[0]
|
||||
}
|
||||
return v.doCheckStructWithParamMap(&doCheckStructWithParamMapInput{
|
||||
Object: object,
|
||||
ParamMap: nil,
|
||||
ParamMapStrict: false,
|
||||
CustomRules: customRules,
|
||||
CustomErrorMessageMap: message,
|
||||
Object: object,
|
||||
ParamMap: nil,
|
||||
UseParamMapInsteadOfObjectValue: false,
|
||||
CustomRules: customRules,
|
||||
CustomErrorMessageMap: message,
|
||||
})
|
||||
}
|
||||
|
||||
@ -59,11 +60,11 @@ func (v *Validator) CheckStructWithParamMap(object interface{}, paramMap interfa
|
||||
message = customErrorMessageMap[0]
|
||||
}
|
||||
return v.doCheckStructWithParamMap(&doCheckStructWithParamMapInput{
|
||||
Object: object,
|
||||
ParamMap: paramMap,
|
||||
ParamMapStrict: true,
|
||||
CustomRules: customRules,
|
||||
CustomErrorMessageMap: message,
|
||||
Object: object,
|
||||
ParamMap: paramMap,
|
||||
UseParamMapInsteadOfObjectValue: true,
|
||||
CustomRules: customRules,
|
||||
CustomErrorMessageMap: message,
|
||||
})
|
||||
}
|
||||
|
||||
@ -147,13 +148,13 @@ func (v *Validator) doCheckStructWithParamMap(input *doCheckStructWithParamMapIn
|
||||
return nil
|
||||
}
|
||||
// Input parameter map handling.
|
||||
if input.ParamMap == nil || !input.ParamMapStrict {
|
||||
if input.ParamMap == nil || !input.UseParamMapInsteadOfObjectValue {
|
||||
inputParamMap = make(map[string]interface{})
|
||||
} else {
|
||||
inputParamMap = gconv.Map(input.ParamMap)
|
||||
}
|
||||
// Checks and extends the parameters map with struct alias tag.
|
||||
if !input.ParamMapStrict {
|
||||
if !input.UseParamMapInsteadOfObjectValue {
|
||||
for nameOrTag, field := range fieldMap {
|
||||
inputParamMap[nameOrTag] = field.Value.Interface()
|
||||
if nameOrTag != field.Name() {
|
||||
@ -174,7 +175,9 @@ func (v *Validator) doCheckStructWithParamMap(input *doCheckStructWithParamMapIn
|
||||
}
|
||||
// It here extends the params map using alias names.
|
||||
if _, ok := inputParamMap[name]; !ok {
|
||||
inputParamMap[name] = field.Value.Interface()
|
||||
if !input.UseParamMapInsteadOfObjectValue {
|
||||
inputParamMap[name] = field.Value.Interface()
|
||||
}
|
||||
}
|
||||
if _, ok := checkRules[name]; !ok {
|
||||
if _, ok := checkRules[fieldName]; ok {
|
||||
@ -187,7 +190,7 @@ func (v *Validator) doCheckStructWithParamMap(input *doCheckStructWithParamMapIn
|
||||
}
|
||||
errorRules = append(errorRules, name+"@"+rule)
|
||||
} else {
|
||||
// The passed rules can overwrite the rules in struct tag.
|
||||
// The input rules can overwrite the rules in struct tag.
|
||||
continue
|
||||
}
|
||||
if len(msg) > 0 {
|
||||
@ -229,10 +232,7 @@ func (v *Validator) doCheckStructWithParamMap(input *doCheckStructWithParamMapIn
|
||||
// The following logic is the same as some of CheckMap.
|
||||
var value interface{}
|
||||
for key, rule := range checkRules {
|
||||
value = nil
|
||||
if v, ok := inputParamMap[key]; ok {
|
||||
value = v
|
||||
}
|
||||
_, value = gutil.MapPossibleItemByKey(inputParamMap, key)
|
||||
// It checks each rule and its value in loop.
|
||||
if e := v.doCheck(key, value, rule, customMessage[key], inputParamMap); e != nil {
|
||||
_, item := e.FirstItem()
|
||||
|
||||
@ -9,6 +9,7 @@ package gvalid
|
||||
import (
|
||||
"github.com/gogf/gf/internal/empty"
|
||||
"github.com/gogf/gf/util/gconv"
|
||||
"github.com/gogf/gf/util/gutil"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
@ -26,17 +27,19 @@ func (v *Validator) checkRequired(value interface{}, ruleKey, rulePattern string
|
||||
// Example: required-if: id,1,age,18
|
||||
case "required-if":
|
||||
required = false
|
||||
array := strings.Split(rulePattern, ",")
|
||||
var (
|
||||
array = strings.Split(rulePattern, ",")
|
||||
foundValue interface{}
|
||||
)
|
||||
// It supports multiple field and value pairs.
|
||||
if len(array)%2 == 0 {
|
||||
for i := 0; i < len(array); {
|
||||
tk := array[i]
|
||||
tv := array[i+1]
|
||||
if v, ok := dataMap[tk]; ok {
|
||||
if strings.Compare(tv, gconv.String(v)) == 0 {
|
||||
required = true
|
||||
break
|
||||
}
|
||||
_, foundValue = gutil.MapPossibleItemByKey(dataMap, tk)
|
||||
if strings.Compare(tv, gconv.String(foundValue)) == 0 {
|
||||
required = true
|
||||
break
|
||||
}
|
||||
i += 2
|
||||
}
|
||||
@ -46,18 +49,21 @@ func (v *Validator) checkRequired(value interface{}, ruleKey, rulePattern string
|
||||
// Example: required-unless: id,1,age,18
|
||||
case "required-unless":
|
||||
required = true
|
||||
array := strings.Split(rulePattern, ",")
|
||||
var (
|
||||
array = strings.Split(rulePattern, ",")
|
||||
foundValue interface{}
|
||||
)
|
||||
// It supports multiple field and value pairs.
|
||||
if len(array)%2 == 0 {
|
||||
for i := 0; i < len(array); {
|
||||
tk := array[i]
|
||||
tv := array[i+1]
|
||||
if v, ok := dataMap[tk]; ok {
|
||||
if strings.Compare(tv, gconv.String(v)) == 0 {
|
||||
required = false
|
||||
break
|
||||
}
|
||||
_, foundValue = gutil.MapPossibleItemByKey(dataMap, tk)
|
||||
if strings.Compare(tv, gconv.String(foundValue)) == 0 {
|
||||
required = false
|
||||
break
|
||||
}
|
||||
|
||||
i += 2
|
||||
}
|
||||
}
|
||||
@ -66,9 +72,13 @@ func (v *Validator) checkRequired(value interface{}, ruleKey, rulePattern string
|
||||
// Example: required-with:id,name
|
||||
case "required-with":
|
||||
required = false
|
||||
array := strings.Split(rulePattern, ",")
|
||||
var (
|
||||
array = strings.Split(rulePattern, ",")
|
||||
foundValue interface{}
|
||||
)
|
||||
for i := 0; i < len(array); i++ {
|
||||
if !empty.IsEmpty(dataMap[array[i]]) {
|
||||
_, foundValue = gutil.MapPossibleItemByKey(dataMap, array[i])
|
||||
if !empty.IsEmpty(foundValue) {
|
||||
required = true
|
||||
break
|
||||
}
|
||||
@ -78,9 +88,13 @@ func (v *Validator) checkRequired(value interface{}, ruleKey, rulePattern string
|
||||
// Example: required-with:id,name
|
||||
case "required-with-all":
|
||||
required = true
|
||||
array := strings.Split(rulePattern, ",")
|
||||
var (
|
||||
array = strings.Split(rulePattern, ",")
|
||||
foundValue interface{}
|
||||
)
|
||||
for i := 0; i < len(array); i++ {
|
||||
if empty.IsEmpty(dataMap[array[i]]) {
|
||||
_, foundValue = gutil.MapPossibleItemByKey(dataMap, array[i])
|
||||
if empty.IsEmpty(foundValue) {
|
||||
required = false
|
||||
break
|
||||
}
|
||||
@ -90,9 +104,13 @@ func (v *Validator) checkRequired(value interface{}, ruleKey, rulePattern string
|
||||
// Example: required-with:id,name
|
||||
case "required-without":
|
||||
required = false
|
||||
array := strings.Split(rulePattern, ",")
|
||||
var (
|
||||
array = strings.Split(rulePattern, ",")
|
||||
foundValue interface{}
|
||||
)
|
||||
for i := 0; i < len(array); i++ {
|
||||
if empty.IsEmpty(dataMap[array[i]]) {
|
||||
_, foundValue = gutil.MapPossibleItemByKey(dataMap, array[i])
|
||||
if empty.IsEmpty(foundValue) {
|
||||
required = true
|
||||
break
|
||||
}
|
||||
@ -102,9 +120,13 @@ func (v *Validator) checkRequired(value interface{}, ruleKey, rulePattern string
|
||||
// Example: required-with:id,name
|
||||
case "required-without-all":
|
||||
required = true
|
||||
array := strings.Split(rulePattern, ",")
|
||||
var (
|
||||
array = strings.Split(rulePattern, ",")
|
||||
foundValue interface{}
|
||||
)
|
||||
for i := 0; i < len(array); i++ {
|
||||
if !empty.IsEmpty(dataMap[array[i]]) {
|
||||
_, foundValue = gutil.MapPossibleItemByKey(dataMap, array[i])
|
||||
if !empty.IsEmpty(foundValue) {
|
||||
required = false
|
||||
break
|
||||
}
|
||||
|
||||
@ -357,11 +357,22 @@ func Test_CheckStruct_InvalidRule(t *testing.T) {
|
||||
func TestValidator_CheckStructWithParamMap(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
type UserApiSearch struct {
|
||||
Uid int64 `json:"uid" v:"required"`
|
||||
Nickname string `json:"nickname" v:"required-with:Uid"`
|
||||
Uid int64 `v:"required"`
|
||||
Nickname string `v:"required-with:uid"`
|
||||
}
|
||||
data := UserApiSearch{
|
||||
Uid: 1,
|
||||
Nickname: "john",
|
||||
}
|
||||
t.Assert(gvalid.CheckStructWithParamMap(data, g.Map{"uid": 1, "nickname": "john"}, nil), nil)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
type UserApiSearch struct {
|
||||
Uid int64 `v:"required"`
|
||||
Nickname string `v:"required-with:uid"`
|
||||
}
|
||||
data := UserApiSearch{}
|
||||
t.Assert(gvalid.CheckStructWithParamMap(data, g.Map{}, nil), nil)
|
||||
t.AssertNE(gvalid.CheckStructWithParamMap(data, g.Map{}, nil), nil)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
type UserApiSearch struct {
|
||||
@ -398,6 +409,6 @@ func TestValidator_CheckStructWithParamMap(t *testing.T) {
|
||||
StartTime: gtime.Now(),
|
||||
EndTime: nil,
|
||||
}
|
||||
t.AssertNE(gvalid.CheckStructWithParamMap(data, g.Map{}, nil), nil)
|
||||
t.AssertNE(gvalid.CheckStructWithParamMap(data, g.Map{"start_time": gtime.Now()}, nil), nil)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user