game/common/serialization/serialization.go

150 lines
4.0 KiB
Go
Raw Normal View History

2025-05-31 23:34:58 +08:00
package serialization
import (
2025-06-04 13:08:58 +08:00
"github.com/fox/fox/log"
"github.com/mitchellh/mapstructure"
"reflect"
2025-06-04 13:08:58 +08:00
"time"
)
2025-05-31 23:34:58 +08:00
2025-06-04 13:08:58 +08:00
func StructToMap(_struct interface{}) map[string]interface{} {
var result map[string]interface{}
err := mapstructure.Decode(_struct, &result)
if err != nil {
log.ErrorF("struct:%v to map error:%v", _struct, err)
return make(map[string]interface{})
2025-05-31 23:34:58 +08:00
}
2025-06-04 13:08:58 +08:00
return result
2025-05-31 23:34:58 +08:00
}
2025-06-04 13:08:58 +08:00
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))
}
2025-06-04 13:08:58 +08:00
return data, nil
}
2025-06-04 13:08:58 +08:00
func MapToStruct[T any](maps map[string]string) (*T, error) {
result := &resultT[T]{}
config := &mapstructure.DecoderConfig{
WeaklyTypedInput: true, // 允许弱类型转换(如 "1" → 1
DecodeHook: stringToTimeHook, // 自定义钩子
Result: &result.ret,
}
decoder, err := mapstructure.NewDecoder(config)
if err != nil {
log.ErrorF("map:%v to struct error:%v", maps, err)
return nil, err
}
2025-06-04 13:08:58 +08:00
err = decoder.Decode(maps)
if err != nil {
log.ErrorF("map:%v to struct error:%v", maps, err)
return nil, err
}
2025-06-04 13:08:58 +08:00
return &result.ret, nil
}
2025-06-04 13:08:58 +08:00
// 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
// }
2025-06-04 13:08:58 +08:00
// 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
// }