Golang 自定义 JSON 序列化(对于 json 是否存在与 gob.register()

使用 json 编码/解码时,有没有办法序列化自定义结构?


假设您有 3 个(在我的实际代码中有 10 个)不同的自定义结构,它们通过 udp 发送,并且您使用 json 进行编码:


type a struct {

   Id   int

   Data msgInfo

}


type b struct {

   Id       int

   Data     msgInfo

   Other    metaInfo

}


type c struct {

   Other    metaInfo

}

在接收端,您想知道接收到的结构体是 a、b 或 c 类型,因此它可以例如传递到类型特定的通道。


type msgtype reflect.Type


.

.


nrOfBytes, err := udpConn.Read(recievedBytes)

if err != nil {...}


var msg interface{}

err = json.Unmarshal(recievedBytes[0:nrOfBytes], &msg)

if err != nil {...}


u := reflect.ValueOf(msg)

msgType := u.Type()

fmt.Printf("msg is of type: %s\n", msgType)

使用 gob,这很容易通过注册类型来完成,但我必须使用 json,因为它是通过 udp 进行通信的,所以无论如何要序列化自定义结构?我想要打印


msg is of type: a

但我只是得到


msg is of type: map[string]interface {}


森林海
浏览 190回答 2
2回答

RISEBY

您可以做的一件事是使用json.RawMessage类型和自定义包装器类型。然后,在收到消息后,您可以进行切换(或使用构造函数映射)来获取正确的结构。例如(省略错误检查):package mainimport (       "encoding/json"    "fmt"  )          type Message struct {    Type string    Data json.RawMessage}          func (m Message) Struct() interface{} {    unmarshaller, found := unmarshallers[m.Type]    if !found {        return nil    }          return unmarshaller([]byte(m.Data))}          type Foo struct {    ID int }          var unmarshallers = map[string]func([]byte) interface{}{    "foo": func(raw []byte) interface{} {        var f Foo        json.Unmarshal(raw, &f)        return f    },     }          func main() {    var body = []byte(`{"Type":"foo","Data":{"ID":1}}`)    var msg Message    json.Unmarshal(body, &msg)    switch s := msg.Struct().(type) {    case Foo:        fmt.Println(s)    }      }请参阅此游乐场示例以获取现场演示http://play.golang.org/p/7FmQqnWPaE

潇潇雨雨

根据您的评论,这可能是一个解决方案:type Packet {  Type string  Data []byte}编码功能:func packageEncode(i interface{}) ([]byte, error) {  b, err := json.Marshal(i)  if err != nil {    return nil, err  }  p := &Package{Data: b}  switch t.(type) {    case a:      p.Type = "a"    case b:      p.Type = "b"    case c:      p.Type = "c"  }  return json.Marshal(p)}然后,当收到消息并解码时:p := &Package{}err = json.Unmarshal(recievedBytes[0:nrOfBytes], p)...if p.Type == "a" {  msg := &a{}  err = json.Unmarshal(p.Data, msg)}if p.Type == "b" {  ...}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go