add Flatten function
add Test case for Flatten() function
pull/16/head
Dean Karn 10 years ago
parent 3614803628
commit 399fda949a
  1. 33
      validator.go
  2. 71
      validator_test.go

@ -31,7 +31,7 @@ type FieldValidationError struct {
// This is intended for use in development + debugging and not intended to be a production error message. // This is intended for use in development + debugging and not intended to be a production error message.
// it also allows FieldValidationError to be used as an Error interface // it also allows FieldValidationError to be used as an Error interface
func (e FieldValidationError) Error() string { func (e *FieldValidationError) Error() string {
return fmt.Sprintf(validationFieldErrMsg, e.Field, e.ErrorTag) return fmt.Sprintf(validationFieldErrMsg, e.Field, e.ErrorTag)
} }
@ -48,7 +48,7 @@ type StructValidationErrors struct {
// This is intended for use in development + debugging and not intended to be a production error message. // This is intended for use in development + debugging and not intended to be a production error message.
// it also allows StructValidationErrors to be used as an Error interface // it also allows StructValidationErrors to be used as an Error interface
func (e StructValidationErrors) Error() string { func (e *StructValidationErrors) Error() string {
s := fmt.Sprintf(validationStructErrMsg, e.Struct) s := fmt.Sprintf(validationStructErrMsg, e.Struct)
@ -63,6 +63,35 @@ func (e StructValidationErrors) Error() string {
return fmt.Sprintf("%s\n\n", s) return fmt.Sprintf("%s\n\n", s)
} }
// Flatten flattens the StructValidationErrors hierarchical sctructure into a flat namespace style field name
// for those that want/need it
func (e *StructValidationErrors) Flatten() map[string]*FieldValidationError {
if e == nil {
return nil
}
errs := map[string]*FieldValidationError{}
for _, f := range e.Errors {
errs[f.Field] = f
}
for key, val := range e.StructErrors {
otherErrs := val.Flatten()
for _, f2 := range otherErrs {
f2.Field = fmt.Sprintf("%s.%s", key, f2.Field)
errs[f2.Field] = f2
}
}
return errs
}
// ValidationFunc that accepts the value of a field and parameter for use in validation (parameter not always used or needed) // ValidationFunc that accepts the value of a field and parameter for use in validation (parameter not always used or needed)
type ValidationFunc func(v interface{}, param string) bool type ValidationFunc func(v interface{}, param string) bool

@ -87,6 +87,72 @@ func AssertFieldError(s *validator.StructValidationErrors, field string, expecte
c.Assert(val.ErrorTag, Equals, expectedTag) c.Assert(val.ErrorTag, Equals, expectedTag)
} }
func AssertMapFieldError(s map[string]*validator.FieldValidationError, field string, expectedTag string, c *C) {
val, ok := s[field]
c.Assert(ok, Equals, true)
c.Assert(val, NotNil)
c.Assert(val.Field, Equals, field)
c.Assert(val.ErrorTag, Equals, expectedTag)
}
func (ms *MySuite) TestFlattening(c *C) {
tSuccess := &TestString{
Required: "Required",
Len: "length==10",
Min: "min=1",
Max: "1234567890",
MinMax: "12345",
OmitEmpty: "",
Sub: &SubTest{
Test: "1",
},
SubIgnore: &SubTest{
Test: "",
},
Anonymous: struct {
A string `validate:"required"`
}{
A: "1",
},
}
err1 := validator.ValidateStruct(tSuccess).Flatten()
c.Assert(err1, IsNil)
tFail := &TestString{
Required: "",
Len: "",
Min: "",
Max: "12345678901",
MinMax: "",
OmitEmpty: "12345678901",
Sub: &SubTest{
Test: "",
},
Anonymous: struct {
A string `validate:"required"`
}{
A: "",
},
}
err2 := validator.ValidateStruct(tFail).Flatten()
// Assert Top Level
c.Assert(err2, NotNil)
// Assert Fields
AssertMapFieldError(err2, "Len", "len", c)
// Assert Struct Field
AssertMapFieldError(err2, "Sub.Test", "required", c)
// Assert Anonymous Struct Field
AssertMapFieldError(err2, "Anonymous.A", "required", c)
}
func (ms *MySuite) TestStructStringValidation(c *C) { func (ms *MySuite) TestStructStringValidation(c *C) {
tSuccess := &TestString{ tSuccess := &TestString{
@ -132,6 +198,7 @@ func (ms *MySuite) TestStructStringValidation(c *C) {
err = validator.ValidateStruct(tFail) err = validator.ValidateStruct(tFail)
// Assert Top Level // Assert Top Level
c.Assert(err, NotNil)
c.Assert(err.Struct, Equals, "TestString") c.Assert(err.Struct, Equals, "TestString")
c.Assert(len(err.Errors), Equals, 6) c.Assert(len(err.Errors), Equals, 6)
c.Assert(len(err.StructErrors), Equals, 2) c.Assert(len(err.StructErrors), Equals, 2)
@ -181,6 +248,7 @@ func (ms *MySuite) TestStructInt32Validation(c *C) {
err = validator.ValidateStruct(tFail) err = validator.ValidateStruct(tFail)
// Assert Top Level // Assert Top Level
c.Assert(err, NotNil)
c.Assert(err.Struct, Equals, "TestInt32") c.Assert(err.Struct, Equals, "TestInt32")
c.Assert(len(err.Errors), Equals, 6) c.Assert(len(err.Errors), Equals, 6)
c.Assert(len(err.StructErrors), Equals, 0) c.Assert(len(err.StructErrors), Equals, 0)
@ -220,6 +288,7 @@ func (ms *MySuite) TestStructUint64Validation(c *C) {
err = validator.ValidateStruct(tFail) err = validator.ValidateStruct(tFail)
// Assert Top Level // Assert Top Level
c.Assert(err, NotNil)
c.Assert(err.Struct, Equals, "TestUint64") c.Assert(err.Struct, Equals, "TestUint64")
c.Assert(len(err.Errors), Equals, 6) c.Assert(len(err.Errors), Equals, 6)
c.Assert(len(err.StructErrors), Equals, 0) c.Assert(len(err.StructErrors), Equals, 0)
@ -259,6 +328,7 @@ func (ms *MySuite) TestStructFloat64Validation(c *C) {
err = validator.ValidateStruct(tFail) err = validator.ValidateStruct(tFail)
// Assert Top Level // Assert Top Level
c.Assert(err, NotNil)
c.Assert(err.Struct, Equals, "TestFloat64") c.Assert(err.Struct, Equals, "TestFloat64")
c.Assert(len(err.Errors), Equals, 6) c.Assert(len(err.Errors), Equals, 6)
c.Assert(len(err.StructErrors), Equals, 0) c.Assert(len(err.StructErrors), Equals, 0)
@ -298,6 +368,7 @@ func (ms *MySuite) TestStructSliceValidation(c *C) {
err = validator.ValidateStruct(tFail) err = validator.ValidateStruct(tFail)
// Assert Top Level // Assert Top Level
c.Assert(err, NotNil)
c.Assert(err.Struct, Equals, "TestSlice") c.Assert(err.Struct, Equals, "TestSlice")
c.Assert(len(err.Errors), Equals, 6) c.Assert(len(err.Errors), Equals, 6)
c.Assert(len(err.StructErrors), Equals, 0) c.Assert(len(err.StructErrors), Equals, 0)

Loading…
Cancel
Save