game/common/serialization/serialization.go

107 lines
2.6 KiB
Go
Raw Normal View History

2025-05-31 23:34:58 +08:00
package serialization
import (
"encoding/json"
"fmt"
"reflect"
"strconv"
)
2025-05-31 23:34: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
}
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
}