Start implementing support for multiple errors
diff --git a/mapstructure.go b/mapstructure.go index d83ad0e..b61070f 100644 --- a/mapstructure.go +++ b/mapstructure.go
@@ -14,6 +14,16 @@ "strings" ) +// Error implements the error interface and can represents multiple +// errors that occur in the course of a single decode. +type Error struct { + Errors []string +} + +func (e *Error) Error() string { + return fmt.Sprintf("%d error(s) decoding", len(e.Errors)) +} + // Decode takes a map and uses reflection to convert it into the // given Go native structure. val must be a pointer to a struct. func Decode(m map[string]interface{}, rawVal interface{}) error { @@ -169,6 +179,8 @@ name, dataValType.Key().Kind()) } + errors := make([]string, 0) + valType := val.Type() for i := 0; i < valType.NumField(); i++ { fieldType := valType.Field(i) @@ -202,9 +214,18 @@ fieldName = fmt.Sprintf("%s.%s", name, fieldName) if err := decode(fieldName, rawMapVal.Interface(), field); err != nil { - return err + switch e := err.(type) { + case *Error: + errors = append(errors, e.Errors...) + default: + errors = append(errors, e.Error()) + } } } + if len(errors) > 0 { + return &Error{errors} + } + return nil }
diff --git a/mapstructure_test.go b/mapstructure_test.go index e913b6c..713e621 100644 --- a/mapstructure_test.go +++ b/mapstructure_test.go
@@ -287,7 +287,13 @@ t.FailNow() } - if err.Error() != "'root.Vstring' expected type 'string', got 'int'" { + derr, ok := err.(*Error) + if !ok { + t.Errorf("error should be kind of Error, instead: %#v", err) + t.FailNow() + } + + if derr.Errors[0] != "'root.Vstring' expected type 'string', got 'int'" { t.Errorf("got unexpected error: %s", err) } }