2025-05-31 23:34:58 +08:00
|
|
|
package serialization
|
|
|
|
|
2025-06-04 02:40:13 +08:00
|
|
|
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
|
|
|
|
}
|
2025-06-04 02:40:13 +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
|
|
|
|
}
|