利用json.RawMessage来动态反序列化
当你在WebSocket编程时,你会在同一个WebSocket连接上发送和接收各种不同的消息。
当你这样做时,您经常会遇到反序列化不同类型消息的问题。
例如作为WebSocket服务器,我们要发送两种类型的消息:
type MessageTypeA struct {
Name string `json:"name"`
Place string `json:"place"`
}
type MessageTypeB struct {
Animal string `json:"animal"`
Thing string `json:"thing"`
}
要发送这些消息,您需要封送这些结构。
并在WebSocket连接上写入这些字节。代码应该类似于:
messageA := MessageTypeA { Name: "Pankhudi", Place: "India"}
// OR
messageB := MessageTypeB { Animal: "dog", Thing: "cap"}
bytes, err := json.Marshal(messageA) // OR messageB
err = websocketConn.WriteMessage(websocket.TextMessage, bytes)
现在,WebSocket客户端的反序列化逻辑事先不知道它将接收什么类型的消息,所以只好每个都尝试一次。
bytes, _, err := websocketConn.Read()
if err != nil {...}
messageA := MessageTypeA{}
// OR
messageB := MessageTypeB{}
json.Unmarshal(dataBytes, &messageA)
// OR
json.Unmarshal(dataBytes, &messageA)
我如何知道要用哪一个结构体来反序列化?json.RawMessage来拯救我们!
在服务器上,让我们创建一个MessageWrapperA结构体,并引入名为MessageType的附加属性,并将实际消息作为“Content”之类的泛型
type MessageWrapperA struct {
MessageType string `json:"message_type"`
MessageTypeA `json:"content"`
}
messageA := MessageWrapperA{
MessageType: "A",
MessageTypeA: MessageTypeA{Name: "Pankhudi", Place: "India"},
}
bytes, _ := json.Marshal(messageA)
然后在客户端我们可以用MessageWrapper结构体先解码,得到MessageType,再根据MessageType来选择具体的结构体二次反序列化即可,代码如下:
type MessageWrapper struct {
MessageType string `json:"message_type"`
Content json.RawMessage `json:"content"`
}
dataBytes, _, err := wsutil.ReadServerData(conn)
_ = json.Unmarshal(dataBytes, &messageWrapper)
if messageWrapper.MessageType == "A" {
subMessage := MessageTypeA{}
_ = json.Unmarshal(messageWrapper.Content, &subMessage)
println(subMessage.Name, subMessage.Place)
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
请问你前端定义的 type MessageWrapper struct { MessageType string
json:"message_type"
Content json.RawMessagejson:"content"
} MessageWrapper 中 Content 的序列化采用的是?Content 数据类型是Uint8Array ?