在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 = %vn", identity.Type, identity.Identity)
} else if identity.Type == "newidentity" && identity.Approved != "" {
fmt.Printf("Got type= %v, with approved status = %vn", identity.Type, identity.Approved)
} else if identity.Type == "roomlist" {
fmt.Printf("Got type= %v, with rooms = %vn", identity.Type, identity.Rooms)
} else if identity.Type == "createroom" {
fmt.Printf("Got type= %v, with roomid = %vn", 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

下面是游乐场的链接

https://play.golang.org/p/eFPj3z-x39-

最新更新