修复序列化bug
This commit is contained in:
parent
165efd717f
commit
41ed9bf0f7
@ -2,14 +2,36 @@ package serialization
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/fox/fox/log"
|
"github.com/fox/fox/log"
|
||||||
"github.com/mitchellh/mapstructure"
|
"github.com/fox/fox/mapstruct"
|
||||||
"reflect"
|
"reflect"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
timeFormat = "2006-01-02 15:04:05"
|
||||||
|
)
|
||||||
|
|
||||||
|
func time2stringHook(v reflect.Value, _ reflect.StructField) (any, error) {
|
||||||
|
if v.Type() == reflect.TypeOf(time.Time{}) {
|
||||||
|
if t, ok := v.Interface().(time.Time); ok {
|
||||||
|
return t.Format(timeFormat), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type resultT[T any] struct {
|
||||||
|
ret T
|
||||||
|
}
|
||||||
|
|
||||||
|
func string2timeHook(s string, _ reflect.StructField) (any, error) {
|
||||||
|
return time.Parse(timeFormat, s)
|
||||||
|
}
|
||||||
|
|
||||||
func StructToMap(_struct interface{}) map[string]interface{} {
|
func StructToMap(_struct interface{}) map[string]interface{} {
|
||||||
var result map[string]interface{}
|
result, err := mapstruct.ToMap(_struct,
|
||||||
err := mapstructure.Decode(_struct, &result)
|
mapstruct.WithTypeHook(reflect.TypeOf(time.Time{}), time2stringHook),
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.ErrorF("struct:%v to map error:%v", _struct, err)
|
log.ErrorF("struct:%v to map error:%v", _struct, err)
|
||||||
return make(map[string]interface{})
|
return make(map[string]interface{})
|
||||||
@ -17,133 +39,10 @@ func StructToMap(_struct interface{}) map[string]interface{} {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
type resultT[T any] struct {
|
|
||||||
ret T
|
|
||||||
}
|
|
||||||
|
|
||||||
func stringToTimeHook(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
|
|
||||||
if t == reflect.TypeOf(time.Time{}) && f == reflect.TypeOf("") {
|
|
||||||
return time.Parse(time.RFC3339, data.(string))
|
|
||||||
}
|
|
||||||
return data, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func MapToStruct[T any](maps map[string]string) (*T, error) {
|
func MapToStruct[T any](maps map[string]string) (*T, error) {
|
||||||
result := &resultT[T]{}
|
result := &resultT[T]{}
|
||||||
config := &mapstructure.DecoderConfig{
|
err := mapstruct.ToStruct(maps, &result.ret,
|
||||||
WeaklyTypedInput: true, // 允许弱类型转换(如 "1" → 1)
|
mapstruct.WithStringTypeHook(reflect.TypeOf(time.Time{}), string2timeHook),
|
||||||
DecodeHook: stringToTimeHook, // 自定义钩子
|
)
|
||||||
Result: &result.ret,
|
return &result.ret, err
|
||||||
}
|
}
|
||||||
|
|
||||||
decoder, err := mapstructure.NewDecoder(config)
|
|
||||||
if err != nil {
|
|
||||||
log.ErrorF("map:%v to struct error:%v", maps, err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = decoder.Decode(maps)
|
|
||||||
if err != nil {
|
|
||||||
log.ErrorF("map:%v to struct error:%v", maps, err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &result.ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// func StructToMap(obj interface{}) map[string]interface{} {
|
|
||||||
// out := make(map[string]interface{})
|
|
||||||
// v := reflect.ValueOf(obj)
|
|
||||||
// if v.Kind() == reflect.Ptr {
|
|
||||||
// v = v.Elem()
|
|
||||||
// }
|
|
||||||
// t := v.Type()
|
|
||||||
// for i := 0; i < v.NumField(); i++ {
|
|
||||||
// field := t.Field(i)
|
|
||||||
// key := field.Tag.Get("json") // 使用 json tag 作为字段名
|
|
||||||
// if key == "" {
|
|
||||||
// key = field.Name
|
|
||||||
// }
|
|
||||||
// out[key] = v.Field(i).Interface()
|
|
||||||
// }
|
|
||||||
// return out
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func keyValueToField(key, value string, fieldValue *reflect.Value) error {
|
|
||||||
// switch fieldValue.Kind() {
|
|
||||||
// case reflect.Int8, reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
||||||
// if v, err := strconv.ParseInt(value, 10, 0); err == nil {
|
|
||||||
// fieldValue.SetInt(v)
|
|
||||||
// } else {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
// case reflect.Uint8, reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
|
||||||
// if v, err := strconv.ParseUint(value, 10, 0); err == nil {
|
|
||||||
// fieldValue.SetUint(v)
|
|
||||||
// } else {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
// case reflect.Float32, reflect.Float64:
|
|
||||||
// if v, err := strconv.ParseFloat(value, 0); err == nil {
|
|
||||||
// fieldValue.SetFloat(v)
|
|
||||||
// } else {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
// case reflect.String:
|
|
||||||
// fieldValue.SetString(value)
|
|
||||||
// case reflect.Bool:
|
|
||||||
// if v, err := strconv.ParseBool(value); err == nil {
|
|
||||||
// fieldValue.SetBool(v)
|
|
||||||
// } else {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
// default:
|
|
||||||
// nv := reflect.New(fieldValue.Type())
|
|
||||||
// if err := json.Unmarshal([]byte(value), nv.Interface()); err == nil {
|
|
||||||
// if fieldValue.Kind() == nv.Elem().Kind() {
|
|
||||||
// fieldValue.Set(nv.Elem())
|
|
||||||
// } else {
|
|
||||||
// return fmt.Errorf("field:%v should have same type.original type:%v, reflect type:%v", key, fieldValue.Kind().String(), nv.Elem().Kind().String())
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return nil
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// func deserializeMapString(kvs map[string]string, structObj interface{}) error {
|
|
||||||
// val := reflect.ValueOf(structObj).Elem()
|
|
||||||
// typ := val.Type()
|
|
||||||
//
|
|
||||||
// for i := 0; i < typ.NumField(); i++ {
|
|
||||||
// field := typ.Field(i)
|
|
||||||
// // 检查字段是否可设置(即导出)
|
|
||||||
// if !field.IsExported() {
|
|
||||||
// continue
|
|
||||||
// }
|
|
||||||
// fieldName := field.Tag.Get("json")
|
|
||||||
// if fieldName == "-" {
|
|
||||||
// continue
|
|
||||||
// }
|
|
||||||
// if value, ok := kvs[fieldName]; ok {
|
|
||||||
// // 获取字段的反射值
|
|
||||||
// fieldValue := val.FieldByName(field.Name)
|
|
||||||
// if err := keyValueToField(field.Tag.Get("json"), value, &fieldValue); err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// return fmt.Errorf("redis:%v not has field:%v ", typ.Name(), field.Tag.Get("json"))
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return nil
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// type resultT[T any] struct {
|
|
||||||
// ret T
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// func MapStringToStruct[T any](maps map[string]string) (*T, error) {
|
|
||||||
// result := &resultT[T]{}
|
|
||||||
// err := deserializeMapString(maps, &result.ret)
|
|
||||||
// return &result.ret, err
|
|
||||||
// }
|
|
||||||
|
@ -1,21 +1,35 @@
|
|||||||
package serialization
|
package serialization
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"fmt"
|
||||||
"game/common/model/user"
|
"game/common/model/user"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_zz(t *testing.T) {
|
func Test_zz(t *testing.T) {
|
||||||
zz := `{\"device_id\":\"\",\"email\":\"\",\"id\":\"17\",\"last_login_ip\":\"114.132.124.145:49486\",\"last_login_time\":\"2025-06-04T02:01:49.72898394+08:00\",\"password\":\"$2a$10$p4GJtWzmhaUcT0i/SNpsWOE6uNq8JzymuB6Lv2Qf0Bpg32YthnWgK\",\"phone\":\"\",\"register_ip\":\"114.132.124.145:49486\",\"register_time\":\"0001-01-01T00:00:00Z\",\"status\":\"1\",\"username\":\"test0001\"}`
|
us := &user.UserAccount{
|
||||||
us := &user.UserAccount{}
|
ID: 17,
|
||||||
_ = json.Unmarshal([]byte(zz), us)
|
Username: "test001",
|
||||||
|
Password: "123456",
|
||||||
|
Email: "",
|
||||||
|
Phone: "",
|
||||||
|
DeviceID: "",
|
||||||
|
LastLoginIP: "127.0.0.1",
|
||||||
|
LastLoginTime: time.Now(),
|
||||||
|
Status: 0,
|
||||||
|
RegisterIP: "",
|
||||||
|
RegisterTime: time.Now(),
|
||||||
|
}
|
||||||
|
maps := StructToMap(us)
|
||||||
|
t.Log(maps)
|
||||||
|
mapString := make(map[string]string)
|
||||||
|
for key, value := range maps {
|
||||||
|
mapString[key] = fmt.Sprintf("%v", value)
|
||||||
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
us, err = MapToStruct[user.UserAccount](map[string]string{
|
us, err = MapToStruct[user.UserAccount](mapString)
|
||||||
"id": "17",
|
|
||||||
"last_login_time": "2025-06-04T02:01:49.72898394+08:00",
|
|
||||||
})
|
|
||||||
t.Log(err)
|
t.Log(err)
|
||||||
t.Log(us)
|
t.Log(us)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user