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 // }