improve association feature for package gvalid

This commit is contained in:
John Guo
2021-11-23 10:42:43 +08:00
parent a96acf6eed
commit 9748b9f70b
9 changed files with 67 additions and 60 deletions

View File

@ -107,7 +107,7 @@ func (r *Request) doParse(pointer interface{}, requestType int) error {
}
}
// Validation.
if err = gvalid.New().Data(pointer, data).Run(r.Context()); err != nil {
if err = gvalid.New().Data(pointer).Assoc(data).Run(r.Context()); err != nil {
return err
}
@ -126,7 +126,7 @@ func (r *Request) doParse(pointer interface{}, requestType int) error {
for i := 0; i < reflectVal2.Len(); i++ {
if err = gvalid.New().
Data(reflectVal2.Index(i), j.Get(gconv.String(i)).Map()).
Data(reflectVal2.Index(i)).Assoc(j.Get(gconv.String(i)).Map()).
Run(r.Context()); err != nil {
return err
}

View File

@ -105,26 +105,33 @@ func (v *Validator) Bail() *Validator {
return newValidator
}
// CaseInsensitive sets the mark for Case-Insensitive for those rules that need value comparison.
func (v *Validator) CaseInsensitive() *Validator {
// Ci sets the mark for Case-Insensitive for those rules that need value comparison.
func (v *Validator) Ci() *Validator {
newValidator := v.Clone()
newValidator.caseInsensitive = true
return newValidator
}
// Data is a chaining operation function, which sets validation data for current operation.
// The optional parameter `assoc` is usually type of map, which specifies the parameter map used in union validation.
// Calling this function with `assoc` also sets `useDataInsteadOfObjectAttributes` true
func (v *Validator) Data(data interface{}, assoc ...interface{}) *Validator {
func (v *Validator) Data(data interface{}) *Validator {
if data == nil {
return v
}
newValidator := v.Clone()
newValidator.data = data
if len(assoc) > 0 {
newValidator.assoc = assoc[0]
newValidator.useDataInsteadOfObjectAttributes = true
return newValidator
}
// Assoc is a chaining operation function, which sets associated validation data for current operation.
// The optional parameter `assoc` is usually type of map, which specifies the parameter map used in union validation.
// Calling this function with `assoc` also sets `useDataInsteadOfObjectAttributes` true
func (v *Validator) Assoc(assoc interface{}) *Validator {
if assoc == nil {
return v
}
newValidator := v.Clone()
newValidator.assoc = assoc
newValidator.useDataInsteadOfObjectAttributes = true
return newValidator
}

View File

@ -550,7 +550,7 @@ func (v *Validator) doCheckValueRecursively(ctx context.Context, in doCheckValue
validator := v.Clone()
validator.rules = nil
validator.messages = nil
if err := validator.Data(reflect.New(in.Type).Interface(), in.Value).Run(ctx); err != nil {
if err := validator.Data(reflect.New(in.Type).Interface()).Assoc(in.Value).Run(ctx); err != nil {
// It merges the errors into single error map.
for k, m := range err.(*validationError).errors {
in.ErrorMaps[k] = m

View File

@ -199,7 +199,7 @@ func ExampleValidator_Rules() {
data := g.Map{
"password": "123",
}
err := g.Validator().Data("", data).
err := g.Validator().Data("").Assoc(data).
Rules("required-with:password").
Messages("请输入确认密码").
Run(gctx.New())
@ -269,7 +269,7 @@ func ExampleValidator_CheckStruct() {
if err := gconv.Scan(data, &user); err != nil {
panic(err)
}
err := g.Validator().Data(user, data).Run(gctx.New())
err := g.Validator().Data(user).Assoc(data).Run(gctx.New())
if err != nil {
fmt.Println(err.Items())
}

View File

@ -414,10 +414,10 @@ func TestValidator_CheckStructWithData(t *testing.T) {
Uid: 1,
Nickname: "john",
}
t.Assert(g.Validator().Data(
data,
g.Map{"uid": 1, "nickname": "john"},
).Run(context.TODO()),
t.Assert(
g.Validator().Data(data).Assoc(
g.Map{"uid": 1, "nickname": "john"},
).Run(context.TODO()),
nil,
)
})
@ -427,7 +427,7 @@ func TestValidator_CheckStructWithData(t *testing.T) {
Nickname string `v:"required-with:uid"`
}
data := UserApiSearch{}
t.AssertNE(g.Validator().Data(data, g.Map{}).Run(context.TODO()), nil)
t.AssertNE(g.Validator().Data(data).Assoc(g.Map{}).Run(context.TODO()), nil)
})
gtest.C(t, func(t *gtest.T) {
type UserApiSearch struct {
@ -437,7 +437,7 @@ func TestValidator_CheckStructWithData(t *testing.T) {
data := UserApiSearch{
Uid: 1,
}
t.AssertNE(g.Validator().Data(data, g.Map{}).Run(context.TODO()), nil)
t.AssertNE(g.Validator().Data(data).Assoc(g.Map{}).Run(context.TODO()), nil)
})
gtest.C(t, func(t *gtest.T) {
@ -451,7 +451,7 @@ func TestValidator_CheckStructWithData(t *testing.T) {
StartTime: nil,
EndTime: nil,
}
t.Assert(g.Validator().Data(data, g.Map{}).Run(context.TODO()), nil)
t.Assert(g.Validator().Data(data).Assoc(g.Map{}).Run(context.TODO()), nil)
})
gtest.C(t, func(t *gtest.T) {
type UserApiSearch struct {
@ -464,6 +464,6 @@ func TestValidator_CheckStructWithData(t *testing.T) {
StartTime: gtime.Now(),
EndTime: nil,
}
t.AssertNE(g.Validator().Data(data, g.Map{"start_time": gtime.Now()}).Run(context.TODO()), nil)
t.AssertNE(g.Validator().Data(data).Assoc(g.Map{"start_time": gtime.Now()}).Run(context.TODO()), nil)
})
}

View File

@ -23,7 +23,7 @@ func Test_CI(t *testing.T) {
t.AssertNil(err)
})
gtest.C(t, func(t *gtest.T) {
err := g.Validator().CaseInsensitive().Rules("in:Id,Name").Data("id").Run(ctx)
err := g.Validator().Ci().Rules("in:Id,Name").Data("id").Run(ctx)
t.AssertNil(err)
})
}

View File

@ -36,7 +36,7 @@ func Test_CustomRule1(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
err := g.Validator().Data("123456").Rules(rule).Messages("custom message").Run(ctx)
t.Assert(err.String(), "custom message")
err = g.Validator().Data("123456", g.Map{"data": "123456"}).Rules(rule).Messages("custom message").Run(ctx)
err = g.Validator().Data("123456").Assoc(g.Map{"data": "123456"}).Rules(rule).Messages("custom message").Run(ctx)
t.Assert(err, nil)
})
// Error with struct validation.
@ -176,7 +176,7 @@ func TestValidator_RuleFunc(t *testing.T) {
err = g.Validator().
Rules(ruleName).
Messages("custom message").
Data("123456", g.Map{"data": "123456"}).
Data("123456").Assoc(g.Map{"data": "123456"}).
RuleFunc(ruleName, ruleFunc).
Run(ctx)
t.AssertNil(err)
@ -232,7 +232,7 @@ func TestValidator_RuleFuncMap(t *testing.T) {
err = g.Validator().
Rules(ruleName).
Messages("custom message").
Data("123456", g.Map{"data": "123456"}).
Data("123456").Assoc(g.Map{"data": "123456"}).
RuleFuncMap(map[string]gvalid.RuleFunc{
ruleName: ruleFunc,
}).Run(ctx)

View File

@ -59,7 +59,7 @@ func Test_CheckStruct_Recursive_Struct_WithData(t *testing.T) {
"Pass2": 200,
},
}
err := g.Validator().Data(user, data).Run(ctx)
err := g.Validator().Data(user).Assoc(data).Run(ctx)
t.AssertNE(err, nil)
t.Assert(err.Maps()["Name"], nil)
t.Assert(err.Maps()["Pass1"], g.Map{"same": "The Pass1 value `100` must be the same as field Pass2"})

View File

@ -44,10 +44,10 @@ func Test_Required(t *testing.T) {
if m := g.Validator().Data("").Rules("required").Messages(nil).Run(ctx); m == nil {
t.Error(m)
}
if m := g.Validator().Data("", map[string]interface{}{"id": 1, "age": 19}).Rules("required-if: id,1,age,18").Messages(nil).Run(ctx); m == nil {
if m := g.Validator().Data("").Assoc(map[string]interface{}{"id": 1, "age": 19}).Rules("required-if: id,1,age,18").Messages(nil).Run(ctx); m == nil {
t.Error("Required校验失败")
}
if m := g.Validator().Data("", map[string]interface{}{"id": 2, "age": 19}).Rules("required-if: id,1,age,18").Messages(nil).Run(ctx); m != nil {
if m := g.Validator().Data("").Assoc(map[string]interface{}{"id": 2, "age": 19}).Rules("required-if: id,1,age,18").Messages(nil).Run(ctx); m != nil {
t.Error("Required校验失败")
}
}
@ -55,20 +55,20 @@ func Test_Required(t *testing.T) {
func Test_RequiredIf(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
rule := "required-if:id,1,age,18"
t.AssertNE(g.Validator().Data("", g.Map{"id": 1}).Rules(rule).Messages(nil).Run(ctx), nil)
t.Assert(g.Validator().Data("", g.Map{"id": 0}).Rules(rule).Messages(nil).Run(ctx), nil)
t.AssertNE(g.Validator().Data("", g.Map{"age": 18}).Rules(rule).Messages(nil).Run(ctx), nil)
t.Assert(g.Validator().Data("", g.Map{"age": 20}).Rules(rule).Messages(nil).Run(ctx), nil)
t.AssertNE(g.Validator().Data("").Assoc(g.Map{"id": 1}).Rules(rule).Messages(nil).Run(ctx), nil)
t.Assert(g.Validator().Data("").Assoc(g.Map{"id": 0}).Rules(rule).Messages(nil).Run(ctx), nil)
t.AssertNE(g.Validator().Data("").Assoc(g.Map{"age": 18}).Rules(rule).Messages(nil).Run(ctx), nil)
t.Assert(g.Validator().Data("").Assoc(g.Map{"age": 20}).Rules(rule).Messages(nil).Run(ctx), nil)
})
}
func Test_RequiredUnless(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
rule := "required-unless:id,1,age,18"
t.Assert(g.Validator().Data("", g.Map{"id": 1}).Rules(rule).Messages(nil).Run(ctx), nil)
t.AssertNE(g.Validator().Data("", g.Map{"id": 0}).Rules(rule).Messages(nil).Run(ctx), nil)
t.Assert(g.Validator().Data("", g.Map{"age": 18}).Rules(rule).Messages(nil).Run(ctx), nil)
t.AssertNE(g.Validator().Data("", g.Map{"age": 20}).Rules(rule).Messages(nil).Run(ctx), nil)
t.Assert(g.Validator().Data("").Assoc(g.Map{"id": 1}).Rules(rule).Messages(nil).Run(ctx), nil)
t.AssertNE(g.Validator().Data("").Assoc(g.Map{"id": 0}).Rules(rule).Messages(nil).Run(ctx), nil)
t.Assert(g.Validator().Data("").Assoc(g.Map{"age": 18}).Rules(rule).Messages(nil).Run(ctx), nil)
t.AssertNE(g.Validator().Data("").Assoc(g.Map{"age": 20}).Rules(rule).Messages(nil).Run(ctx), nil)
})
}
@ -86,9 +86,9 @@ func Test_RequiredWith(t *testing.T) {
"id": 100,
"name": "john",
}
err1 := g.Validator().Data(val1, params1).Rules(rule).Messages(nil).Run(ctx)
err2 := g.Validator().Data(val1, params2).Rules(rule).Messages(nil).Run(ctx)
err3 := g.Validator().Data(val1, params3).Rules(rule).Messages(nil).Run(ctx)
err1 := g.Validator().Data(val1).Assoc(params1).Rules(rule).Messages(nil).Run(ctx)
err2 := g.Validator().Data(val1).Assoc(params2).Rules(rule).Messages(nil).Run(ctx)
err3 := g.Validator().Data(val1).Assoc(params3).Rules(rule).Messages(nil).Run(ctx)
t.Assert(err1, nil)
t.AssertNE(err2, nil)
t.AssertNE(err3, nil)
@ -106,9 +106,9 @@ func Test_RequiredWith(t *testing.T) {
params3 := g.Map{
"time": time.Time{},
}
err1 := g.Validator().Data(val1, params1).Rules(rule).Messages(nil).Run(ctx)
err2 := g.Validator().Data(val1, params2).Rules(rule).Messages(nil).Run(ctx)
err3 := g.Validator().Data(val1, params3).Rules(rule).Messages(nil).Run(ctx)
err1 := g.Validator().Data(val1).Assoc(params1).Rules(rule).Messages(nil).Run(ctx)
err2 := g.Validator().Data(val1).Assoc(params2).Rules(rule).Messages(nil).Run(ctx)
err3 := g.Validator().Data(val1).Assoc(params3).Rules(rule).Messages(nil).Run(ctx)
t.Assert(err1, nil)
t.AssertNE(err2, nil)
t.Assert(err3, nil)
@ -125,9 +125,9 @@ func Test_RequiredWith(t *testing.T) {
params3 := g.Map{
"time": time.Now(),
}
err1 := g.Validator().Data(val1, params1).Rules(rule).Messages(nil).Run(ctx)
err2 := g.Validator().Data(val1, params2).Rules(rule).Messages(nil).Run(ctx)
err3 := g.Validator().Data(val1, params3).Rules(rule).Messages(nil).Run(ctx)
err1 := g.Validator().Data(val1).Assoc(params1).Rules(rule).Messages(nil).Run(ctx)
err2 := g.Validator().Data(val1).Assoc(params2).Rules(rule).Messages(nil).Run(ctx)
err3 := g.Validator().Data(val1).Assoc(params3).Rules(rule).Messages(nil).Run(ctx)
t.Assert(err1, nil)
t.AssertNE(err2, nil)
t.AssertNE(err3, nil)
@ -175,9 +175,9 @@ func Test_RequiredWithAll(t *testing.T) {
"id": 100,
"name": "john",
}
err1 := g.Validator().Data(val1, params1).Rules(rule).Messages(nil).Run(ctx)
err2 := g.Validator().Data(val1, params2).Rules(rule).Messages(nil).Run(ctx)
err3 := g.Validator().Data(val1, params3).Rules(rule).Messages(nil).Run(ctx)
err1 := g.Validator().Data(val1).Assoc(params1).Rules(rule).Messages(nil).Run(ctx)
err2 := g.Validator().Data(val1).Assoc(params2).Rules(rule).Messages(nil).Run(ctx)
err3 := g.Validator().Data(val1).Assoc(params3).Rules(rule).Messages(nil).Run(ctx)
t.Assert(err1, nil)
t.Assert(err2, nil)
t.AssertNE(err3, nil)
@ -198,9 +198,9 @@ func Test_RequiredWithOut(t *testing.T) {
"id": 100,
"name": "john",
}
err1 := g.Validator().Data(val1, params1).Rules(rule).Messages(nil).Run(ctx)
err2 := g.Validator().Data(val1, params2).Rules(rule).Messages(nil).Run(ctx)
err3 := g.Validator().Data(val1, params3).Rules(rule).Messages(nil).Run(ctx)
err1 := g.Validator().Data(val1).Assoc(params1).Rules(rule).Messages(nil).Run(ctx)
err2 := g.Validator().Data(val1).Assoc(params2).Rules(rule).Messages(nil).Run(ctx)
err3 := g.Validator().Data(val1).Assoc(params3).Rules(rule).Messages(nil).Run(ctx)
t.AssertNE(err1, nil)
t.AssertNE(err2, nil)
t.Assert(err3, nil)
@ -221,9 +221,9 @@ func Test_RequiredWithOutAll(t *testing.T) {
"id": 100,
"name": "john",
}
err1 := g.Validator().Data(val1, params1).Rules(rule).Messages(nil).Run(ctx)
err2 := g.Validator().Data(val1, params2).Rules(rule).Messages(nil).Run(ctx)
err3 := g.Validator().Data(val1, params3).Rules(rule).Messages(nil).Run(ctx)
err1 := g.Validator().Data(val1).Assoc(params1).Rules(rule).Messages(nil).Run(ctx)
err2 := g.Validator().Data(val1).Assoc(params2).Rules(rule).Messages(nil).Run(ctx)
err3 := g.Validator().Data(val1).Assoc(params3).Rules(rule).Messages(nil).Run(ctx)
t.AssertNE(err1, nil)
t.Assert(err2, nil)
t.Assert(err3, nil)
@ -914,9 +914,9 @@ func Test_Same(t *testing.T) {
"id": 100,
"name": "john",
}
err1 := g.Validator().Data(val1, params1).Rules(rule).Messages(nil).Run(ctx)
err2 := g.Validator().Data(val1, params2).Rules(rule).Messages(nil).Run(ctx)
err3 := g.Validator().Data(val1, params3).Rules(rule).Messages(nil).Run(ctx)
err1 := g.Validator().Data(val1).Assoc(params1).Rules(rule).Messages(nil).Run(ctx)
err2 := g.Validator().Data(val1).Assoc(params2).Rules(rule).Messages(nil).Run(ctx)
err3 := g.Validator().Data(val1).Assoc(params3).Rules(rule).Messages(nil).Run(ctx)
t.AssertNE(err1, nil)
t.Assert(err2, nil)
t.Assert(err3, nil)
@ -937,9 +937,9 @@ func Test_Different(t *testing.T) {
"id": 100,
"name": "john",
}
err1 := g.Validator().Data(val1, params1).Rules(rule).Messages(nil).Run(ctx)
err2 := g.Validator().Data(val1, params2).Rules(rule).Messages(nil).Run(ctx)
err3 := g.Validator().Data(val1, params3).Rules(rule).Messages(nil).Run(ctx)
err1 := g.Validator().Data(val1).Assoc(params1).Rules(rule).Messages(nil).Run(ctx)
err2 := g.Validator().Data(val1).Assoc(params2).Rules(rule).Messages(nil).Run(ctx)
err3 := g.Validator().Data(val1).Assoc(params3).Rules(rule).Messages(nil).Run(ctx)
t.Assert(err1, nil)
t.AssertNE(err2, nil)
t.AssertNE(err3, nil)