【问题标题】:Decoding generic JSON objects to one of many formats将通用 JSON 对象解码为多种格式之一
【发布时间】:2015-03-17 23:15:21
【问题描述】:

我正在研究一个通用的基于 JSON 的 Go 消息传递协议。我想做的是拥有一个BaseMessage,其中包含Typetimestamp 等一般信息。但同时我希望能够为某些类型的数据定义更具体的消息结构。

例如:

type Message struct {
    Type      string `json:type`
    Timestamp string `json:timestamp`

}

type EventMessage struct {
    Message
    EventType string
    EventCreator string
    EventData interface{}
}

我有一组处理程序,为了确定应该由哪个处理程序处理消息,我首先将 JSON 解码为一般的 Message 类型以检查 Type 字段。对于此示例,我将获取与“事件”消息类型关联的处理程序。

当我想在结构上声明 EventMessage 类型时遇到了问题。

以下代码非常粗略,但希望它显示了我对如何尝试处理消息的总体想法。

type Handler func(msg Message) Message
handlers := make(map[string]Handler)

var msg Message
decoder.Decode(&msg)
handler := handlers[msg.Type]
handler(msg)

我曾尝试使用interface{},但 JSON 解码器只是创建了一个映射,然后我无法断言任何一种类型。我已经找到了使其成为可能的解决方法,但它非常难看,可能效率不高,而且很可能容易出错。我想让事情变得简单明了,以便可以轻松维护此代码。

在 Go 中是否有处理通用 JSON 对象的方法,以便解码的 JSON 可以是多种结构格式之一?

我也尝试过在主 Message 结构中的 Data interface{} 中包含更具体的信息,但后来我遇到了同样的问题,即无法在接口上声明任何类型。必须有更好的方法来处理我刚刚遗漏的 JSON 格式。

【问题讨论】:

    标签: json go unmarshalling


    【解决方案1】:

    处理此问题的一种方法是为消息的固定部分定义一个结构,其中包含json.RawMessage 字段以捕获消息的变体部分。将 json.RawMessage 解码为特定于变体的类型:

    type Message struct {
      Type      string `json:"type"`
      Timestamp string `json:"timestamp"`
      Data      json.RawMessage
    }  
    
    type Event struct {
       Type    string `json:"type"`
       Creator string `json:"creator"`
    }
    
    
    var m Message
    if err := json.Unmarshal(data, &m); err != nil {
        log.Fatal(err)
    }
    switch m.Type {
    case "event":
        var e Event
        if err := json.Unmarshal([]byte(m.Data), &e); err != nil {
            log.Fatal(err)
        }
        fmt.Println(m.Type, e.Type, e.Creator)
    default:
        log.Fatal("bad message type")
    }
    

    playground example

    【讨论】:

    • 谢谢,效果很好。我没想过要使用 RawMessage!
    猜你喜欢
    • 1970-01-01
    • 2020-07-04
    • 2015-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-07
    • 1970-01-01
    相关资源
    最近更新 更多