在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
使用json序列化与反序列化的方式(有一个数字转换的坑)package t8 import ( "encoding/json" "fmt" "testing" ) type Student struct{ Name string `json:"name"` Age int `json:"age"` } // JSON序列化方式 func jsonStructToMap(stuObj *Student) (map[string]interface{}, error){ // 结构体转json strRet, err := json.Marshal(stuObj) if err != nil{ return nil, err } // json转map var mRet map[string]interface{} err1 := json.Unmarshal(strRet, &mRet) if err1 != nil{ return nil, err1 } return mRet, nil } func TestJsonMethod(t *testing.T) { // 测试 struct使用json直接转map stuObj1 := Student{ Name: "whw", Age: 28, } mRet, err := jsonStructToMap(&stuObj1) if err != nil{ panic(fmt.Sprintf("json方式出错: %s \n", err.Error())) } // 查看一下转换后的结果 for key, val := range mRet{ fmt.Printf("key: %v, value: %v, typeValue: %T \n", key, val, val) } /* key: name, value: whw, typeValue: string key: age, value: 28, typeValue: float64 —————————— 注意这里age变成了 float64!!! */ } 使用反射将单层的struct转换为mappackage t8 import ( "fmt" "reflect" "testing" ) //type Student struct{ // Name string `json:"name"` // Age int `json:"age"` //} // ToMap 结构体转为Map[string]interface{} func StructToMapReflect(in interface{}, tagName string) (map[string]interface{}, error) { out := make(map[string]interface{}) v := reflect.ValueOf(in) if v.Kind() == reflect.Ptr { v = v.Elem() } if v.Kind() != reflect.Struct { // 非结构体返回错误提示 return nil, fmt.Errorf("ToMap only accepts struct or struct pointer; got %T", v) } t := v.Type() // 遍历结构体字段 // 指定tagName值为map中key;字段值为map中value for i := 0; i < v.NumField(); i++ { fi := t.Field(i) if tagValue := fi.Tag.Get(tagName); tagValue != "" { out[tagValue] = v.Field(i).Interface() } } return out, nil } func TestReflectMethod(t *testing.T) { stuObj := Student{ Name: "wanghw", Age: 22, } m2, _ := StructToMapReflect(&stuObj,"json") for key, val := range m2{ fmt.Printf("key: %s, val: %v, typeVal: %T \n", key, val, val) } /* key: name, val: wanghw, typeVal: string key: age, val: 22, typeVal: int —————— 这里正常了,age还是int类型 */ } 使用structs包转换单层的struct为map首先需要下载structs包go get github.com/fatih/structs
代码package t8 import ( "fmt" "github.com/fatih/structs" "testing" ) type Student struct { Name string `json:"name"` Age int `json:"age"` } func TestStructsMethod(t *testing.T) { stuObj := Student{ Name: "naruto", Age: 23, } m3 := structs.Map(&stuObj) for key, val := range m3 { fmt.Printf("key: %s, val: %v, typeVal: %T \n", key, val, val) } // key: Name, val: naruto, typeVal: string // key: Age, val: 23, typeVal: int } 使用structs包或反射的方法转换嵌套的结构体为mappackage t8 import ( "fmt" "github.com/fatih/structs" "reflect" "testing" ) // 嵌套结构体转 // 用户信息 type UserInfo struct { Name string `json:"name" structs:"name"` Age int `json:"age" structs:"age"` Profile Profile `json:"profile" structs:"profile"` } // 配置信息 type Profile struct { Hobby string `json:"hobby" structs:"hobby"` } // 声明一个全局user var userObj = UserInfo{ Name: "whw", Age: 18, Profile: Profile{ Hobby: "computer", }, } // TODO 1、structs转换方法 func TestStructsMethod(t *testing.T) { m3 := structs.Map(&userObj) for k, v := range m3 { fmt.Printf("key:%v value:%v value type:%T\n", k, v, v) } /* key:name value:whw value type:string key:age value:18 value type:int key:profile value:map[hobby:computer] value type:map[string]interface {} */ } // TODO 2、使用反射转成单层map(注意结构体中不能有重复的字段!!!) // ToMap2 将结构体转为单层map func ToMap2(in interface{}, tag string) (map[string]interface{}, error) { // 当前函数只接收struct类型 v := reflect.ValueOf(in) if v.Kind() == reflect.Ptr { // 结构体指针 v = v.Elem() } if v.Kind() != reflect.Struct { return nil, fmt.Errorf("ToMap only accepts struct or struct pointer; got %T", v) } out := make(map[string]interface{}) queue := make([]interface{}, 0, 1) queue = append(queue, in) for len(queue) > 0 { v := reflect.ValueOf(queue[0]) if v.Kind() == reflect.Ptr { // 结构体指针 v = v.Elem() } queue = queue[1:] t := v.Type() for i := 0; i < v.NumField(); i++ { vi := v.Field(i) if vi.Kind() == reflect.Ptr { // 内嵌指针 vi = vi.Elem() if vi.Kind() == reflect.Struct { // 结构体 queue = append(queue, vi.Interface()) } else { ti := t.Field(i) if tagValue := ti.Tag.Get(tag); tagValue != "" { // 存入map out[tagValue] = vi.Interface() } } break } if vi.Kind() == reflect.Struct { // 内嵌结构体 queue = append(queue, vi.Interface()) break } // 一般字段 ti := t.Field(i) if tagValue := ti.Tag.Get(tag); tagValue != "" { // 存入map out[tagValue] = vi.Interface() } } } return out, nil } func TestStructToSingleMap(t *testing.T) { m4, _ := ToMap2(&userObj, "json") for k, v := range m4 { fmt.Printf("key:%v value:%v value type:%T\n", k, v, v) } /* key:name value:whw value type:string key:age value:18 value type:int key:hobby value:computer value type:string */ } 参考博客https://www.liwenzhou.com/posts/Go/struct2map/ |
请发表评论