go - 从通用且以某种方式动态映射的内容中获取内容的最佳方法是什么?

标签 go hashmap gorilla

我将这个json转换为:

var leerCHAT []interface{}
但是我要经历疯狂的考验,才能到达 map 上的 map 内部和 map 内部的任何地方,特别是因为某些结果的内容不同。
这是杰森
[
   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之后和ids之前的id是动态的,因此我必须以某种方式获取它,因为它始终只是我执行for range循环来抓取它的一个元素。

最佳答案

索引3处的array元素描述索引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)
    }
}
Run it on the playground

关于go - 从通用且以某种方式动态映射的内容中获取内容的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62698268/

相关文章:

Go SSH 服务器通过 SCP 接受文件传输

go - 在 go 中发布带有数据的请求

algorithm - codility:峰值:在性能部件测试中实现go有什么问题?

ruby - 数组到哈希 Ruby

go - 根据请求处理 XMLFile

session - Golang 和 Gorilla session - 缓存阻止注销功能

mysql - 附加到 JSON 字段的 MySQL 的 GoLang 查询

java - 对具有 2 个字段的 HashMap 进行排序

go - 如何设置 gorilla /websocket 连接以充当浏览器应用程序的 JSON-RPC 客户端?

ruby - 如何将两个嵌套数据结构合并为一个?