Recognize TextUnmarshaler and use it
This change recognizes TextUnmarshaler during object mapping, and
will defer to it when we have a string but are assigning to a
non-string target that implements the interface.
package mapper
import (
+ "encoding"
"fmt"
"reflect"
"strings"
@@ -161,6 +162,7 @@ func (md *mapper) DecodeField(tree Object, ty reflect.Type, key string, target i
}
var emptyObject map[string]interface{}
+var textUnmarshalerType = reflect.TypeOf(new(encoding.TextUnmarshaler)).Elem()
// adjustValue converts if possible to produce the target type.
func (md *mapper) adjustValue(val reflect.Value, to reflect.Type, ty reflect.Type, key string) (reflect.Value, error) {
@@ -264,6 +266,18 @@ func (md *mapper) adjustValue(val reflect.Value, to reflect.Type, ty reflect.Typ
return val, fmt.Errorf(
"Cannot decode Object to type %v; it isn't a struct, and no custom decoder exists", to)
}
+ } else if val.Type().Kind() == reflect.String {
+ // If the source is a string, see if the target implements encoding.TextUnmarshaler.
+ target := reflect.New(to)
+ if target.Type().Implements(textUnmarshalerType) {
+ um := target.Interface().(encoding.TextUnmarshaler)
+ if err := um.UnmarshalText([]byte(val.String())); err != nil {
+ return val, err
+ }
+ val = target.Elem()
+ } else {
+ break
+ }
} else {
break
}
