Golang将通用JSON对象解码为多种格式之一 [英] Golang Decoding Generic JSON Objects to One of Many Formats
问题描述
我正在研究一种基于通用JSON的消息传递协议。我想要做的是有一个 BaseMessage
,它具有一般信息,如类型
,时间戳
等,但同时我希望能够为特定类型的数据定义更具体的消息结构。
例如:
类型消息struct {
类型字符串`json:type`
时间戳字符串`json:timestamp`
类型EventMessage结构{
消息
EventType字符串
EventCreator字符串
EventData接口{}
}
我有一组处理程序并确定哪个处理程序应该处理消息我将JSON解码为一般 Message
首先键入以检查 Type
字段。对于这个例子,我会得到与事件消息类型相关联的处理程序。
当我想要将 EventMessage
类型声明为结构时遇到问题。
以下代码非常粗糙,但希望它显示我对如何处理消息的一般想法。
类型Handler func(msg Message)消息
handlers:= make(map [string] Handler)
var msg消息
decoder.Decode(& msg)
handler:= handlers [msg.Type]
handler(msg)
我试图使用 interface {}
,但是JSON解码器只是创建一个映射,然后我不能断言任何一种类型。我已经想出了可能的解决方法,但它非常难看,可能效率不高,并且很可能出现错误。我想保持简单直接的事情,这样可以很容易地维护这些代码。
是否有一种方法可以处理Golang中的通用JSON对象,以便解码JSON可以是许多结构格式之一吗?
我也玩过在数据接口{}
在主要的 Message
struct中,但是我遇到了同样的问题,无法在接口上声明任何类型。必须有更好的方式来处理我只是缺少的JSON格式。
处理这个问题的一种方法是定义用于 json.RawMessage 字段的消息的固定部分的结构来捕获变体部分的消息。将json.RawMessage解码为特定于该变体的类型:
type消息struct {
类型字符串`json:类型`
时间戳字符串`json:timestamp`
数据json.RawMessage
}
类型事件结构{
类型字符串`json:type`
Creator字符串`json:creator`
}
var m消息
如果err:= json.Unmarshal(data,& m); err!= nil {
log.Fatal(err)
}
switch m.Type {
caseevent:
var e Event
if err:= json.Unmarshal([] byte(m.Data),& e); err!= nil {
log.Fatal(err)
}
fmt.Println(m.Type,e.Type,e.Creator)
默认值:
log.Fatal(bad message type)
}
I am working on a general JSON based message passing protocol in golang. What I would like to do is have a BaseMessage
that has general information like Type
, timestamp
, etc. But at the same time I want to be able to define more specific message structures for certain types of data.
For example:
type Message struct {
Type string `json:type`
Timestamp string `json:timestamp`
}
type EventMessage struct {
Message
EventType string
EventCreator string
EventData interface{}
}
I have a set of handlers and to determine which handler should process the message I decode the JSON to the general Message
type first to check the Type
field. For this example I would get the handler associated with an "Event" message type.
I run into problems when I then want to assert the EventMessage
type onto the structure.
The following code is very rough, but hopefully it displays my general idea of how I am trying to handle the messages.
type Handler func(msg Message) Message
handlers := make(map[string]Handler)
var msg Message
decoder.Decode(&msg)
handler := handlers[msg.Type]
handler(msg)
I have tried to use an interface{}
but then the JSON decoder just creates a map which I then cant assert either type on. I have figured out workarounds that make it possible, but its very ugly, probably not efficient, and most likely error prone. I would like to keep things simple and straightforward so this code can be easily maintained.
Is there a method of handling generic JSON objects in Golang so that the decoded JSON could be one of many struct formats?
I have also played with the idea of having more specific info in a Data interface{}
in the main Message
struct, but then I run into the same problem of not being able to assert any types onto the interface. There has to be a better way to handle JSON formats that I am just missing.
One way to handle this is to define a struct for the fixed part of the message with a json.RawMessage field to capture the variant part of the message. Decode the json.RawMessage to a type specific to the variant:
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")
}
这篇关于Golang将通用JSON对象解码为多种格式之一的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!