用于在Golang中将结构转换为映射的函数

用于在Golang中将结构转换为映射的函数,go,Go,我想将结构转换为Golang中的映射。如果我可以在创建的映射中使用JSON标记作为键(否则默认为字段名),那也很好 编辑日期:2020年12月14日 由于回购已存档,因此您可以使用 编辑TL;DR版本,2015年6月15日 如果您想要将结构转换为贴图的快速解决方案,请参阅,升级并使用该软件包 快乐编码!:) 原职 到目前为止,我有这个功能,我使用的反映包,但我不知道如何使用该软件包,请与我的容忍 func ConvertToMap(model interface{}) bson.M {

我想将结构转换为Golang中的映射。如果我可以在创建的映射中使用JSON标记作为键(否则默认为字段名),那也很好

编辑日期:2020年12月14日 由于回购已存档,因此您可以使用

编辑TL;DR版本,2015年6月15日 如果您想要将结构转换为贴图的快速解决方案,请参阅,升级并使用该软件包

快乐编码!:)


原职 到目前为止,我有这个功能,我使用的反映包,但我不知道如何使用该软件包,请与我的容忍

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
}
func ConvertToMap(模型接口{})bson.M{
ret:=bson.M{}
modelReflect:=reflect.ValueOf(模型)
如果modelReflect.Kind()==reflect.Ptr{
modelReflect=modelReflect.Elem()
}
modelRefType:=modelReflect.Type()
FieldScont:=modelReflect.NumField()
变量字段数据接口{}
对于i:=0;i

我还查看了JSON包的源代码,因为它应该包含我需要的实现(或部分实现),但不太了解。

这里是我以前编写的一个函数,它使用标记作为键将结构转换为映射

// 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
}
//ToMap使用结构的标记将结构转换为映射。
//
//ToMap使用struct字段上的标记来决定要将哪些字段添加到
//返回地图。
func-ToMap(在接口{}中,标记字符串)(映射[string]接口{},错误){
out:=make(映射[字符串]接口{})
v:=反射值(英寸)
如果v.Kind()==reflect.Ptr{
v=v.Elem()
}
//我们只接受结构
如果v.Kind()!=reflect.Struct{
返回nil,fmt.Errorf(“ToMap只接受结构;得到%T”,v)
}
类型:=v.类型()
对于i:=0;i
可运行


注意,如果有多个字段具有相同的标记值,则显然无法将它们全部存储在地图中。如果出现这种情况,返回一个错误可能是明智的。

我也需要类似的东西。我使用的是一个内部包,它将结构转换为映射。我决定用其他基于
struct
的高级函数来开源它。看看:

它支持:

  • 将结构转换为映射
  • 将结构的字段提取为
    []字符串
  • 将结构的值提取到
    []值
  • 检查结构是否已初始化
  • 检查传递的接口是结构还是指向结构的指针
您可以在这里看到一些示例: 例如,将结构转换为映射很简单:

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)

structs
包支持匿名(嵌入)字段和嵌套结构。该包提供通过字段标记过滤某些字段的功能

struct
map[string]接口{}

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

主包装
进口(
“fmt”
“反映”
)
类型票据结构{
N1整数
N2串
n3字符串
}
func main(){
a:=法案{4,“dhfthf”,“fdgdf”}
v:=反射值(a)
值:=make(映射[string]接口{},v.NumField())
对于i:=0;i
对于接受的答案,我喜欢importable包,但它不会转换我的json别名。我的大多数项目都有一个我导入的助手函数/类

这里有一个函数可以解决我的具体问题


//将结构转换为映射,同时将json别名保留为键
func structomap(obj接口{})(newMap映射[string]接口{},err error){
data,err:=json.Marshal(obj)//转换为json字符串
如果错误!=零{
返回
}
err=json.Unmarshal(data,&newMap)//转换为映射
返回
}
总的来说,这就是它的名称

主程序包
进口(
“fmt”
“编码/json”
“github.com/fatih/structs”
)
类型MyStructObject struct{
电子邮件字符串`json:“电子邮件地址”`
}
func main(){
对象:=&MyStructObject{Email:test@test.com"}
//我的解决方案
fmt.Println(StructToMap(obj))//打印{“电子邮件地址”:test@test.com"}
//当前接受的解决方案
fmt.Println(structs.Map(obj))//打印{“Email”:test@test.com"}
}

您在这里是否有特定的目标?如果您正在处理
mgo/bson
包(由于使用了
bson.M
),它是否已经从类似于
encoding/json
的结构执行了转换?@JamesHenstridge是的,它已经将结构转换为bson表示。我还可以使用bson.marshall(从struct)/unmarshall(到map)来执行转换。但是想制作一个直接将结构转换为映射的函数,它涉及反射、打包,使用起来既慢又麻烦;json的
json
包就是这样的,因为使用反射很困难。我的建议是要么使用
package main

import (
    "fmt"
    "reflect"
)

type bill struct {
    N1 int
    N2 string
    n3 string
}

func main() {
    a := bill{4, "dhfthf", "fdgdf"}

    v := reflect.ValueOf(a)

    values := make(map[string]interface{}, v.NumField())

    for i := 0; i < v.NumField(); i++ {
        if v.Field(i).CanInterface() {
            values[v.Type().Field(i).Name] = v.Field(i).Interface()
        } else {
            fmt.Printf("sorry you have a unexported field (lower case) value you are trying to sneak past. I will not allow it: %v\n", v.Type().Field(i).Name)
        }
    }

    fmt.Println(values)

    passObject(&values)
}

func passObject(v1 *map[string]interface{}) {
    fmt.Println("yoyo")
}
map := Structpb.AsMap()

// map is the map[string]interface{}