Функция преобразования структуры в карту в Голанге
Я хочу преобразовать структуру в карту в Голанге. Было бы неплохо, если бы я мог использовать теги JSON как ключи в созданной карте (в противном случае по умолчанию было бы имя поля).
Редактировать TL; версия DR, 15 июня 2015 г.
Если вы хотите, чтобы быстрое решение для преобразования структуры в карту, см. принятый ответ, увеличьте его и используйте этот пакет.
Счастливое кодирование!:)
Оригинальное сообщение
Пока у меня есть эта функция, я использую пакет отражения, но я не понимаю, как использовать пакет, пожалуйста, не стесняйтесь.
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
}
Также я посмотрел исходный код пакета JSON, потому что он должен содержать мою нужную реализацию (или ее части), но не слишком много понимает.
Ответы
Ответ 1
Мне также нужно было что-то вроде этого. Я использовал внутренний пакет, который преобразовывал структуру в карту. Я решил открыть его с помощью других функций высокого уровня struct
. Посмотрите:
https://github.com/fatih/structs
Он поддерживает:
- Преобразование структуры в карту
- Извлеките поля структуры в
[]string
- Извлеките значения структуры в
[]values
- Проверьте, была ли инициализирована структура или нет
- Проверьте, является ли переданный интерфейс структурой или указателем на struct
Здесь вы можете увидеть несколько примеров: 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)
Пакет structs
поддерживает анонимные (встроенные) поля и вложенные структуры. Пакет обеспечивает фильтрацию определенных полей с помощью тегов полей.
Ответ 2
От 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)
}
}
пойти на площадку здесь
Ответ 3
Вот функция, которую я написал в прошлом, чтобы преобразовать структуру в карту, используя теги в виде ключей
// ToMap converts a struct to a map using the struct 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
}
Runnable пример здесь.
Обратите внимание, что если у вас несколько полей с одинаковым значением тега, вы, очевидно, не сможете хранить их на карте. Возможно, разумно вернуть ошибку, если это произойдет.
Ответ 4
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")
}
Ответ 5
Я не могу рекомендовать достаточно https://github.com/mitchellh/mapstructure, который преобразует структуры в карты и наоборот очень гладким способом.