我想在Golang中将结构转换为map.如果我可以将JSON标记用作创建的映射中的键(否则默认为字段名称),这也是很好的.
如果您想要将结构转换为映射的快速解决方案,请参阅接受的答案,对其进行upvote并使用该包.
快乐的编码!:)
到目前为止我有这个功能,我正在使用反射包但我不明白如何使用该包,请耐心等待.
func ConvertToMap(model interface{}) bson.M {
ret := bson.M{}
modelReflect := reflect.ValueOf(model)
if modelReflect.Kind() == reflect.Ptr {
modelReflect = modelReflect.Elem()
}
modelRefType := modelReflect.Type()
fieldsCount := modelReflect.NumField()
var fieldData interface{}
for i := 0; i < fieldsCount; i++ {
field := modelReflect.Field(i)
switch field.Kind() {
case reflect.Struct:
fallthrough
case reflect.Ptr:
fieldData = ConvertToMap(field.Interface())
default:
fieldData = field.Interface()
}
ret[modelRefType.Field(i).Name] = fieldData
}
return ret
}
Run Code Online (Sandbox Code Playgroud)
另外我查看了JSON包源代码,因为它应该包含我需要的实现(或部分内容)但不太了解.
Fat*_*lan 113
我也需要这样的东西.我正在使用一个将结构转换为地图的内部包.我决定用其他struct基于高级功能开源.看一看:
https://github.com/fatih/structs
它支持:
[]string[]values你可以在这里看到一些例子:http://godoc.org/github.com/fatih/structs#pkg-examples 例如将结构转换为地图很简单:
type Server struct {
Name string
ID int32
Enabled bool
}
s := &Server{
Name: "gopher",
ID: 123456,
Enabled: true,
}
// => {"Name":"gopher", "ID":123456, "Enabled":true}
m := structs.Map(s)
Run Code Online (Sandbox Code Playgroud)
该structs软件包支持匿名(嵌入)字段和嵌套结构.该包提供通过字段标签过滤某些字段.
Zan*_*tsu 24
从struct到map[string]interface{}
package main
import (
"fmt"
"encoding/json"
)
type MyData struct {
One int
Two string
Three int
}
func main() {
in := &MyData{One: 1, Two: "second"}
var inInterface map[string]interface{}
inrec, _ := json.Marshal(in)
json.Unmarshal(inrec, &inInterface)
// iterate through inrecs
for field, val := range inInterface {
fmt.Println("KV Pair: ", field, val)
}
}
Run Code Online (Sandbox Code Playgroud)
Edw*_*rdr 10
这是我过去编写的一个函数,用于将结构转换为地图,使用标记作为键
// ToMap converts a struct to a map using the struct's tags.
//
// ToMap uses tags on struct fields to decide which fields to add to the
// returned map.
func ToMap(in interface{}, tag string) (map[string]interface{}, error){
out := make(map[string]interface{})
v := reflect.ValueOf(in)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
// we only accept structs
if v.Kind() != reflect.Struct {
return nil, fmt.Errorf("ToMap only accepts structs; got %T", v)
}
typ := v.Type()
for i := 0; i < v.NumField(); i++ {
// gets us a StructField
fi := typ.Field(i)
if tagv := fi.Tag.Get(tag); tagv != "" {
// set key of map to value in struct field
out[tagv] = v.Field(i).Interface()
}
}
return out, nil
}
Run Code Online (Sandbox Code Playgroud)
可运行在这里的例子.
请注意,如果您有多个具有相同标记值的字段,那么您显然无法将它们全部存储在地图中.如果发生这种情况,返回错误可能是谨慎的.
小智 7
我喜欢接受答案的可导入包,但它不会翻译我的 json 别名。我的大多数项目都有一个我导入的辅助函数/类。
这是一个解决我的具体问题的函数。
// Converts a struct to a map while maintaining the json alias as keys
func StructToMap(obj interface{}) (newMap map[string]interface{}, err error) {
data, err := json.Marshal(obj) // Convert to a json string
if err != nil {
return
}
err = json.Unmarshal(data, &newMap) // Convert to a map
return
}
Run Code Online (Sandbox Code Playgroud)
总的来说,这就是它的名字......
package main
import (
"fmt"
"encoding/json"
"github.com/fatih/structs"
)
type MyStructObject struct {
Email string `json:"email_address"`
}
func main() {
obj := &MyStructObject{Email: "test@test.com"}
// My solution
fmt.Println(StructToMap(obj)) // prints {"email_address": "test@test.com"}
// The currently accepted solution
fmt.Println(structs.Map(obj)) // prints {"Email": "test@test.com"}
}
Run Code Online (Sandbox Code Playgroud)