# #json #go #unmarshalling
Вопрос:
Я внедрил сервер чата в golang на основе протокола TCP. Связь между клиентом и сервером использует 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.
Комментарии:
1. Может быть, вам нужно использовать
map[string]string
.
Ответ №1:
Вместо того, чтобы создавать разные структуры, я бы предложил вам использовать одну структуру и разбирать значения в ней, а после разбора значений вы можете написать пользовательские обработчики на основе ваших требований.
Также в приведенном выше примере вы не разделяете каждое сообщение на 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, amp;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" amp;amp; identity.Identity != "" {
fmt.Printf("Got type= %v, with identity = %vn", identity.Type, identity.Identity)
} else if identity.Type == "newidentity" amp;amp; 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
Ниже также приведена ссылка на игровую площадку