为什么要去 json.Unmarshal auto convert interface{}

程序会收到很多 msg,msg 有不同的结构“Data”,所以我定义了 Msg 结构:


type Msg struct {

    MsgType int

    Data interface{}

}

type Data1 struct {

//msg type 1 Data struct

}

type Data2 struct {

//msg type 2 Data struct

}

func (msgStr string) {

    msg := Msg{}

    if err := json.Unmarshal([]byte(msgStr), &msg); err != nil {

        //log err

    }

    switch msg.MsgType{

    case 1:

        //convert msg.Data to a type 1 struct

    case 2:

        //convert msg.Data to a type 2 struct

    }

}

但是打印出 msg.Data,它是一个映射,而不是 interface{},所以当我通过 msg.Data.(Data1) 将它转换为 Data1 时,出现错误。

那么,

1. 为什么 interface{} 自动转换为 map?

2.如何转换成我想要的Data1结构?

3.这个场景的最佳实践是什么。


牧羊人nacy
浏览 119回答 1
1回答

翻阅古今

1. 因为它看到一个 JSON 对象,并且如文档所述,map[string]interface{}当存储到一个 JSON 对象时变成一个interface{}(这是一般情况下可以保存 JSON 对象中任何内容的唯一类型)。2. 鉴于您目前的情况,您可以将地图的每个字段分配给新的Data1或的适当字段Data2。3. 处理这个问题的理想方法是使用json.RawMessage延迟解码Data直到你知道它是什么。这可以这样处理:type Msg struct {  MsgType int  Data interface{}}func (m *Msg) UnmarshalJSON(b []byte) (err error) {    var tmp struct {        MsgType int        Data json.RawMessage    }    err = json.Unmarshal(b, &tmp)    if err != nil {        return    }    m.MsgType = tmp.MsgType    switch (tmp.MsgType) {    case 1:        data := Data1{}        err = json.Unmarshal(tmp.Data, &data)        if err != nil {            return        }        m.Data = data    case 2:        data := Data2{}        err = json.Unmarshal(tmp.Data, &data)        if err != nil {            return        }        m.Data = data    default:        return errors.New("invalid DataType")    }    return}然后你可以调用json.Unmarshalorjson.Decode直接在 a 上*Msg,它Data会根据你的需要进行解码。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go