diff --git a/deepobject.go b/deepobject.go index 5fb4ae0..10a9c21 100644 --- a/deepobject.go +++ b/deepobject.go @@ -2,6 +2,7 @@ package runtime import ( "bytes" + "encoding" "encoding/json" "errors" "fmt" @@ -55,8 +56,16 @@ func marshalDeepObject(in interface{}, path []string) ([]string, error) { // into a deepObject style set of subscripts. [a, b, c] turns into // [a][b][c] prefix := "[" + strings.Join(path, "][") + "]" + + var value string + if t == nil { + value = "null" + } else { + value = fmt.Sprintf("%v", t) + } + result = []string{ - prefix + fmt.Sprintf("=%v", t), + prefix + fmt.Sprintf("=%s", value), } } return result, nil @@ -268,6 +277,7 @@ func assignPathValues(dst interface{}, pathValues fieldOrValue) error { dst = reflect.Indirect(aPtr) } dst.Set(reflect.ValueOf(date)) + return nil } if it.ConvertibleTo(reflect.TypeOf(time.Time{})) { var tm time.Time @@ -288,6 +298,13 @@ func assignPathValues(dst interface{}, pathValues fieldOrValue) error { dst = reflect.Indirect(aPtr) } dst.Set(reflect.ValueOf(tm)) + return nil + } + // For other struct types that implement TextUnmarshaler (e.g. uuid.UUID), + // use that for binding. This comes after the legacy Date/time.Time checks + // above which have special fallback format handling. + if tu, ok := v.Interface().(encoding.TextUnmarshaler); ok { + return tu.UnmarshalText([]byte(pathValues.value)) } fieldMap, err := fieldIndicesByJSONTag(iv.Interface()) if err != nil { diff --git a/deepobject_test.go b/deepobject_test.go index 409c9cb..7425a9f 100644 --- a/deepobject_test.go +++ b/deepobject_test.go @@ -63,6 +63,7 @@ func TestDeepObject(t *testing.T) { om := map[string]int{ "additional": 1, } + d := MockBinder{Time: time.Date(2020, 2, 1, 0, 0, 0, 0, time.UTC)} two := 2