从通用且动态的 go 地图获取内容的最佳方式是什么?
Whats the best way to get content from a generic and somehow dynamic go map?
我将这个 json 转换为:
var leerCHAT []interface{}
但我正在经历疯狂的篮球,以到达地图内部地图和地图内部疯狂的地图上的任何点,特别是因为一些结果是不同的内容。
这是 Json
[
null,
null,
"hub:zWXroom",
"presence_diff",
{
"joins":{
"f718a187-6e96-4d62-9c2d-67aedea00000":{
"metas":[
{
"context":{},
"permissions":{},
"phx_ref":"zNDwmfsome=",
"phx_ref_prev":"zDMbRTmsome=",
"presence":"lobby",
"profile":{},
"roles":{}
}
]
}
},
"leaves":{}
}
]
我需要进入配置文件然后里面有一个“DisplayName”字段。
所以我一直在做疯狂的黑客..即使这样我也被卡在了一半...
首先是一个数组,所以我可以做一些事情[elementnumber]
然后是棘手的映射开始的时候......
抱歉所有打印等是为了调试并查看我返回的元素数量。
if leerCHAT[3] == "presence_diff" {
var id string
presence := leerCHAT[4].(map[string]interface{})
log.Printf("algo: %v", len(presence))
log.Printf("algo: %s", presence["joins"])
vamos := presence["joins"].(map[string]interface{})
for i := range vamos {
log.Println(i)
id = i
}
log.Println(len(vamos))
vamonos := vamos[id].(map[string]interface{})
log.Println(vamonos)
log.Println(len(vamonos))
metas := vamonos["profile"].(map[string]interface{}) \\ I get error here..
log.Println(len(metas))
}
到目前为止,我可以一直看到 meta:{...} 但无法继续将我的 hacky 代码变成我需要的东西。
注意:由于在 Joins: 之后和 metas: 之前的 id 是动态的,所以我必须以某种方式获取它,因为它始终只是一个元素,所以我使用 for range 循环来获取它。
索引 3 处的数组元素描述了索引 4 处变体 JSON 的类型。
以下是解码 JSON 到 Go 值的方法。首先,为 JSON:
的每个变体部分声明 Go 类型
type PrescenceDiff struct {
Joins map[string]*Presence // declaration of Presence type to be supplied
Leaves map[string]*Presence
}
type Message struct {
Body string
}
声明一个将类型字符串关联到 Go 类型的映射:
var messageTypes = map[string]reflect.Type{
"presence_diff": reflect.TypeOf(&PresenceDiff{}),
"message": reflect.TypeOf(&Message{}),
// add more types here as needed
}
将变体部分解码为raw message。使用索引 3 处元素中的名称创建适当 Go 类型的值并解码为该值:
func decode(data []byte) (interface{}, error) {
var messageType string
var raw json.RawMessage
v := []interface{}{nil, nil, nil, &messageType, &raw}
err := json.Unmarshal(data, &v)
if err != nil {
return nil, err
}
if len(raw) == 0 {
return nil, errors.New("no message")
}
t := messageTypes[messageType]
if t == nil {
return nil, fmt.Errorf("unknown message type: %q", messageType)
}
result := reflect.New(t.Elem()).Interface()
err = json.Unmarshal(raw, result)
return result, err
}
使用type switches访问消息的变体部分:
defer ws.Close()
for {
_, data, err := ws.ReadMessage()
if err != nil {
log.Printf("Read error: %v", err)
break
}
v, err := decode(data)
if err != nil {
log.Printf("Decode error: %v", err)
continue
}
switch v := v.(type) {
case *PresenceDiff:
fmt.Println(v.Joins, v.Leaves)
case *Message:
fmt.Println(v.Body)
default:
fmt.Printf("type %T not handled\n", v)
}
}
我将这个 json 转换为:
var leerCHAT []interface{}
但我正在经历疯狂的篮球,以到达地图内部地图和地图内部疯狂的地图上的任何点,特别是因为一些结果是不同的内容。 这是 Json
[
null,
null,
"hub:zWXroom",
"presence_diff",
{
"joins":{
"f718a187-6e96-4d62-9c2d-67aedea00000":{
"metas":[
{
"context":{},
"permissions":{},
"phx_ref":"zNDwmfsome=",
"phx_ref_prev":"zDMbRTmsome=",
"presence":"lobby",
"profile":{},
"roles":{}
}
]
}
},
"leaves":{}
}
]
我需要进入配置文件然后里面有一个“DisplayName”字段。
所以我一直在做疯狂的黑客..即使这样我也被卡在了一半...
首先是一个数组,所以我可以做一些事情[elementnumber] 然后是棘手的映射开始的时候...... 抱歉所有打印等是为了调试并查看我返回的元素数量。
if leerCHAT[3] == "presence_diff" {
var id string
presence := leerCHAT[4].(map[string]interface{})
log.Printf("algo: %v", len(presence))
log.Printf("algo: %s", presence["joins"])
vamos := presence["joins"].(map[string]interface{})
for i := range vamos {
log.Println(i)
id = i
}
log.Println(len(vamos))
vamonos := vamos[id].(map[string]interface{})
log.Println(vamonos)
log.Println(len(vamonos))
metas := vamonos["profile"].(map[string]interface{}) \\ I get error here..
log.Println(len(metas))
}
到目前为止,我可以一直看到 meta:{...} 但无法继续将我的 hacky 代码变成我需要的东西。
注意:由于在 Joins: 之后和 metas: 之前的 id 是动态的,所以我必须以某种方式获取它,因为它始终只是一个元素,所以我使用 for range 循环来获取它。
索引 3 处的数组元素描述了索引 4 处变体 JSON 的类型。
以下是解码 JSON 到 Go 值的方法。首先,为 JSON:
的每个变体部分声明 Go 类型type PrescenceDiff struct {
Joins map[string]*Presence // declaration of Presence type to be supplied
Leaves map[string]*Presence
}
type Message struct {
Body string
}
声明一个将类型字符串关联到 Go 类型的映射:
var messageTypes = map[string]reflect.Type{
"presence_diff": reflect.TypeOf(&PresenceDiff{}),
"message": reflect.TypeOf(&Message{}),
// add more types here as needed
}
将变体部分解码为raw message。使用索引 3 处元素中的名称创建适当 Go 类型的值并解码为该值:
func decode(data []byte) (interface{}, error) {
var messageType string
var raw json.RawMessage
v := []interface{}{nil, nil, nil, &messageType, &raw}
err := json.Unmarshal(data, &v)
if err != nil {
return nil, err
}
if len(raw) == 0 {
return nil, errors.New("no message")
}
t := messageTypes[messageType]
if t == nil {
return nil, fmt.Errorf("unknown message type: %q", messageType)
}
result := reflect.New(t.Elem()).Interface()
err = json.Unmarshal(raw, result)
return result, err
}
使用type switches访问消息的变体部分:
defer ws.Close()
for {
_, data, err := ws.ReadMessage()
if err != nil {
log.Printf("Read error: %v", err)
break
}
v, err := decode(data)
if err != nil {
log.Printf("Decode error: %v", err)
continue
}
switch v := v.(type) {
case *PresenceDiff:
fmt.Println(v.Joins, v.Leaves)
case *Message:
fmt.Println(v.Body)
default:
fmt.Printf("type %T not handled\n", v)
}
}