json - 在 go 中使用通用类型字段解组不同的 JSON 消息
问题描述
我已经基于 TCP 协议在 golang 中实现了一个聊天服务器。客户端到服务器的通信使用 JSON 并使用一个简单的协议,该协议通过换行符 (\n) 分隔消息。有几种有效的消息类型包含不同的字段,但它们都包含一个声明消息类型的通用类型字段。一些示例如下所示。
{"type" : "newidentity", "identity" : "Adel"}
{"type" : "newidentity", "approved" : "true"}
{
"type" : "roomlist",
"rooms" : ["MainHall-s1", "MainHall-s2", "jokes"]
}
{"type" : "createroom", "roomid" : "jokes"}
下面显示了在服务器上处理传入消息的部分(不是实际代码,只是一个示例)。
func handleConnection(c net.Conn) {
fmt.Print(".")
for {
netData, err := bufio.NewReader(c).ReadString('\n')
if err != nil {
fmt.Println(err)
return
}
res, err := json.Marshal(IdentitySuccess{MessageType: "newidentity", Approved: "approved"})
if err != nil {
fmt.Printf("Error: %v", err)
}
c.Write([]byte(string(res) + "\n"))
}
c.Close()
}
所以我想从这些 JSON 消息(上面代码片段中的 netData)创建结构并在应用程序中使用这些结构。用公共字段解组这些不同的 JSON 字符串并从中获取结构的最简单方法是什么?所以理想情况下,我想要一个函数,它输出接收到的 JSON 文本的类型和结构。
解决方案
我建议您不要创建不同的结构,而是使用一个结构并将值解组到其中,在解组值之后,您可以根据您的要求编写自定义处理程序。
同样在上面的示例中,您没有用 . 分隔每条消息\n
。但是,如果您在一行中有一条消息,那么您可以做的就是这样。
package main
import (
"encoding/json"
"fmt"
"strings"
)
type IdentitySuccess struct {
Type string `json:"type"`
Identity string `json:"identity,omitempty"`
Approved string `json:"approved,omitempty"`
Rooms []string `json:"rooms,omitempty"`
Roomid string `json:"roomid,omitempty"`
}
func Process(data []byte) (IdentitySuccess, error) {
var r IdentitySuccess
err := json.Unmarshal(data, &r)
return r, err
}
func main() {
jsonData :=
`{"type" : "newidentity", "identity" : "Adel"}
{"type" : "newidentity", "approved" : "true"}
{"type" : "roomlist","rooms" : ["MainHall-s1", "MainHall-s2", "jokes"]}
{"type" : "createroom", "roomid" : "jokes"}`
// Because you are taking \n as a seperator and all of this is coming in one response
jsons := strings.Split(jsonData, "\n")
for _, json := range jsons {
identity, err := Process([]byte(json))
if err != nil {
panic(err)
}
// Custom handlers will be applied here on the basis of the struct values
if identity.Type == "newidentity" && identity.Identity != "" {
fmt.Printf("Got type= %v, with identity = %v\n", identity.Type, identity.Identity)
} else if identity.Type == "newidentity" && identity.Approved != "" {
fmt.Printf("Got type= %v, with approved status = %v\n", identity.Type, identity.Approved)
} else if identity.Type == "roomlist" {
fmt.Printf("Got type= %v, with rooms = %v\n", identity.Type, identity.Rooms)
} else if identity.Type == "createroom" {
fmt.Printf("Got type= %v, with roomid = %v\n", identity.Type, identity.Roomid)
}
}
}
上述片段的输出将是这个
Got type= newidentity, with identity = Adel
Got type= newidentity, with approved status = true
Got type= roomlist, with rooms = [MainHall-s1 MainHall-s2 jokes]
Got type=createroom, with roomid = jokes
下面也是操场链接
推荐阅读
- json - 如何连接2个表,其中一个表中的数据有需要解析的JSON数据?
- html - 如何在容器上方覆盖元素
- php - 从多维数组的第三级获取数据列
- axios - 在 Nuxt asyncData 中使用 axios 在浏览器刷新时丢失令牌
- azure-keyvault - 如何在ARM中为dependsOn引用子资源
- vue.js - 如何使用 Jest 创建 Vue 实例(未定义 Vue)
- excel - 仅将字符串添加到活动合并单元格一次 - Excel VBA 宏
- python - 通过 Python 将列从一个现有的 excel 文件复制到另一个文件
- jsf - 将 Richfaces333 + JSF 1.2 迁移到 Richfaces 4.3.7.Final + JSF 2.2:缺少标签
- python - Python跟踪mudule,解释输出