为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
森林海 2022-01-04 10:00:59
使用 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 {}
查看完整描述

2 回答

?
RISEBY

TA贡献1856条经验 获得超5个赞

您可以做的一件事是使用json.RawMessage类型和自定义包装器类型。然后,在收到消息后,您可以进行切换(或使用构造函数映射)来获取正确的结构。


例如(省略错误检查):


package main


import (   

    "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


查看完整回答
反对 回复 2022-01-04
?
潇潇雨雨

TA贡献1833条经验 获得超4个赞

根据您的评论,这可能是一个解决方案:


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" {

  ...

}


查看完整回答
反对 回复 2022-01-04
  • 2 回答
  • 0 关注
  • 188 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号