game/common/serialization/serialization.go
2025-06-04 13:08:58 +08:00

150 lines
4.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package serialization
import (
"github.com/fox/fox/log"
"github.com/mitchellh/mapstructure"
"reflect"
"time"
)
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{})
}
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) {
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
}
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
// }