从通用且以某种方式动态映射的内容中获取内容的最佳方法是什么? [英] Whats the best way to get content from a generic and somehow dynamic go map?
问题描述
我将这个json转换为:
I have this json that I convert to:
var leerCHAT []interface{}
但是我要经过疯狂的考验才能到达地图上地图内的任何点以及地图内的疯狂,特别是因为某些结果是不同的内容.这是杰森
but I am going through crazy hoops to get to any point on that map inside map and inside map crazyness, specially because some results are different content. this is the 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"字段.
I need to get to profile then inside there is a "DisplayName" field.
所以我一直在疯狂地进行黑客攻击..甚至像这样,我也被卡住了一半...
so I been doing crazy hacks.. and even like this I got stuck half way...
首先是一个数组,所以我可以做点什么[elementnumber]然后是棘手的映射开始的时候...抱歉,所有打印等信息都在调试中,查看我返回的元素数量.
First is an array so I can just do something[elementnumber] then is when the tricky mapping starts... SORRY about all the prints etc is to debug and see the number of elements I am getting back.
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))
}
到目前为止,我可以一直看到元数据:{...},但是无法继续将我的hacky代码添加到我需要的内容中.
so far I can see all the way to the meta:{...} but can't continue with my hacky code into what I need.
注意:自从Joins:之后和metas:之前的id是动态的以来,我必须以某种方式获取它,因为它始终只是我执行for range循环来抓取它的一个元素.
NOTICE: that since the id after Joins: and before metas: is dynamic I have to get it somehow since is always just one element I did the for range loop to grab it.
推荐答案
索引3处的数组元素描述索引4处的变体JSON的类型.
The array element at index 3 describes the type of the variant JSON at index 4.
以下是将JSON解码为Go值的方法.首先,为JSON的每个变体部分声明Go类型:
Here's how to decode the JSON to Go values. First, declare Go types for each of the variant parts of the JSON:
type PrescenceDiff struct {
Joins map[string]*Presence // declaration of Presence type to be supplied
Leaves map[string]*Presence
}
type Message struct {
Body string
}
声明将类型字符串与Go类型相关联的映射:
Declare a map associating the type string to the Go type:
var messageTypes = map[string]reflect.Type{
"presence_diff": reflect.TypeOf(&PresenceDiff{}),
"message": reflect.TypeOf(&Message{}),
// add more types here as needed
}
将变体部分解码为原始消息.在索引3的元素中使用名称来创建合适的Go类型的值并将其解码为该值:
Decode the variant part to a raw message. Use use the name in the element at index 3 to create a value of the appropriate Go type and decode to that value:
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
}
使用类型开关访问消息的变体部分:
Use type switches to access the variant part of the message:
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)
}
}
这篇关于从通用且以某种方式动态映射的内容中获取内容的最佳方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!