| @@ -4,6 +4,7 @@ import ( | |||||
| "encoding/json" | "encoding/json" | ||||
| "fmt" | "fmt" | ||||
| "reflect" | "reflect" | ||||
| "time" | |||||
| mp "github.com/mitchellh/mapstructure" | mp "github.com/mitchellh/mapstructure" | ||||
| ) | ) | ||||
| @@ -26,12 +27,30 @@ type TypedSerderOption struct { | |||||
| TypeFieldName string | TypeFieldName string | ||||
| } | } | ||||
| func parseTimeHook(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { | |||||
| if t != reflect.TypeOf(time.Time{}) { | |||||
| return data, nil | |||||
| } | |||||
| switch f.Kind() { | |||||
| case reflect.String: | |||||
| return time.Parse(time.RFC3339, data.(string)) | |||||
| case reflect.Float64: | |||||
| return time.Unix(0, int64(data.(float64))*int64(time.Millisecond)), nil | |||||
| case reflect.Int64: | |||||
| return time.Unix(0, data.(int64)*int64(time.Millisecond)), nil | |||||
| default: | |||||
| return data, nil | |||||
| } | |||||
| } | |||||
| func MapToObject(m map[string]any, obj any) error { | func MapToObject(m map[string]any, obj any) error { | ||||
| config := &mp.DecoderConfig{ | config := &mp.DecoderConfig{ | ||||
| TagName: "json", | TagName: "json", | ||||
| Squash: true, | Squash: true, | ||||
| WeaklyTypedInput: true, | WeaklyTypedInput: true, | ||||
| Result: obj, | Result: obj, | ||||
| DecodeHook: mp.ComposeDecodeHookFunc(parseTimeHook), | |||||
| } | } | ||||
| decoder, err := mp.NewDecoder(config) | decoder, err := mp.NewDecoder(config) | ||||
| @@ -2,6 +2,7 @@ package serder | |||||
| import ( | import ( | ||||
| "testing" | "testing" | ||||
| "time" | |||||
| . "github.com/smartystreets/goconvey/convey" | . "github.com/smartystreets/goconvey/convey" | ||||
| myreflect "gitlink.org.cn/cloudream/common/utils/reflect" | myreflect "gitlink.org.cn/cloudream/common/utils/reflect" | ||||
| @@ -31,6 +32,31 @@ func Test_MapToObject(t *testing.T) { | |||||
| So(st.C, ShouldEqual, 1234) | So(st.C, ShouldEqual, 1234) | ||||
| }) | }) | ||||
| Convey("包含Time,先从结构体转为JSON,再从JSON转为Map,最后变回结构体", t, func() { | |||||
| type Struct struct { | |||||
| Time time.Time | |||||
| NilTime *time.Time | |||||
| } | |||||
| var st = Struct{ | |||||
| Time: time.Now(), | |||||
| NilTime: nil, | |||||
| } | |||||
| data, err := ObjectToJSON(st) | |||||
| So(err, ShouldBeNil) | |||||
| var mp map[string]any | |||||
| err = JSONToObject(data, &mp) | |||||
| So(err, ShouldBeNil) | |||||
| var st2 Struct | |||||
| err = MapToObject(mp, &st2) | |||||
| So(err, ShouldBeNil) | |||||
| So(st.Time, ShouldEqual, st2.Time) | |||||
| So(st.NilTime, ShouldEqual, st2.NilTime) | |||||
| }) | |||||
| } | } | ||||
| func Test_TypedMapToObject(t *testing.T) { | func Test_TypedMapToObject(t *testing.T) { | ||||