Skip to content

Commit fba18d7

Browse files
committed
Support maps and slices in Validate
1 parent c3144fd commit fba18d7

File tree

2 files changed

+81
-11
lines changed

2 files changed

+81
-11
lines changed

validator.go

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -232,21 +232,18 @@ func (mv *Validator) SetValidationFunc(name string, vf ValidationFunc) error {
232232
return nil
233233
}
234234

235-
// Validate validates the fields of a struct based
236-
// on 'validator' tags and returns errors found indexed
237-
// by the field name.
235+
// Validate calls the Validate method on the default validator.
238236
func Validate(v interface{}) error {
239237
return defaultValidator.Validate(v)
240238
}
241239

242-
// Validate validates the fields of a struct based
243-
// on 'validator' tags and returns errors found indexed
244-
// by the field name.
240+
// Validate validates the fields of structs (included embedded structs) based on
241+
// 'validator' tags and returns errors found indexed by the field name.
245242
func (mv *Validator) Validate(v interface{}) error {
246243
m := make(ErrorMap)
247-
if err := mv.validateStruct(reflect.ValueOf(v), m); err != nil {
248-
return err
249-
}
244+
mv.deepValidateCollection(reflect.ValueOf(v), m, func() string {
245+
return ""
246+
})
250247
if len(m) > 0 {
251248
return m
252249
}
@@ -334,11 +331,16 @@ func (mv *Validator) deepValidateCollection(f reflect.Value, m ErrorMap, fnameFn
334331
case reflect.Struct:
335332
subm := make(ErrorMap)
336333
err := mv.validateStruct(f, subm)
334+
parentName := fnameFn()
337335
if err != nil {
338-
m[fnameFn()] = ErrorArray{err}
336+
m[parentName] = ErrorArray{err}
339337
}
340338
for j, k := range subm {
341-
m[fnameFn()+"."+j] = k
339+
keyName := j
340+
if parentName != "" {
341+
keyName = parentName + "." + keyName
342+
}
343+
m[keyName] = k
342344
}
343345
case reflect.Array, reflect.Slice:
344346
// we don't need to loop over every byte in a byte slice so we only end up

validator_test.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,74 @@ func (ms *MySuite) TestJSONPrintNoTag(c *C) {
699699
c.Assert(errs["B"], HasError, validator.ErrLen)
700700
}
701701

702+
func (ms *MySuite) TestValidateSlice(c *C) {
703+
type test2 struct {
704+
Num int `validate:"max=2"`
705+
String string `validate:"nonzero"`
706+
}
707+
708+
err := validator.Validate([]test2{
709+
{
710+
Num: 6,
711+
String: "foo",
712+
},
713+
{
714+
Num: 1,
715+
String: "foo",
716+
},
717+
})
718+
c.Assert(err, NotNil)
719+
errs, ok := err.(validator.ErrorMap)
720+
c.Assert(ok, Equals, true)
721+
c.Assert(errs["[0].Num"], HasError, validator.ErrMax)
722+
c.Assert(errs["[0].String"], IsNil) // sanity check
723+
c.Assert(errs["[1].Num"], IsNil) // sanity check
724+
c.Assert(errs["[1].String"], IsNil) // sanity check
725+
}
726+
727+
func (ms *MySuite) TestValidateMap(c *C) {
728+
type test2 struct {
729+
Num int `validate:"max=2"`
730+
String string `validate:"nonzero"`
731+
}
732+
733+
err := validator.Validate(map[string]test2{
734+
"first": {
735+
Num: 6,
736+
String: "foo",
737+
},
738+
"second": {
739+
Num: 1,
740+
String: "foo",
741+
},
742+
})
743+
c.Assert(err, NotNil)
744+
errs, ok := err.(validator.ErrorMap)
745+
c.Assert(ok, Equals, true)
746+
c.Assert(errs["[first](value).Num"], HasError, validator.ErrMax)
747+
c.Assert(errs["[first](value).String"], IsNil) // sanity check
748+
c.Assert(errs["[second](value).Num"], IsNil) // sanity check
749+
c.Assert(errs["[second](value).String"], IsNil) // sanity check
750+
751+
err = validator.Validate(map[test2]string{
752+
{
753+
Num: 6,
754+
String: "foo",
755+
}: "first",
756+
{
757+
Num: 1,
758+
String: "foo",
759+
}: "second",
760+
})
761+
c.Assert(err, NotNil)
762+
errs, ok = err.(validator.ErrorMap)
763+
c.Assert(ok, Equals, true)
764+
c.Assert(errs["[{Num:6 String:foo}](key).Num"], HasError, validator.ErrMax)
765+
c.Assert(errs["[{Num:6 String:foo}](key).String"], IsNil) // sanity check
766+
c.Assert(errs["[{Num:1 String:foo}](key).Num"], IsNil) // sanity check
767+
c.Assert(errs["[{Num:1 String:foo}](key).String"], IsNil) // sanity check
768+
}
769+
702770
type hasErrorChecker struct {
703771
*CheckerInfo
704772
}

0 commit comments

Comments
 (0)