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