How to unmarshal JSON into interface{} in Go?

huangapple go评论74阅读模式
英文:

How to unmarshal JSON into interface{} in Go?

问题

我是一个Go语言的新手,现在我遇到了一个问题。我有一个名为Message的类型,它是一个结构体,定义如下:

type Message struct {
    Cmd  string      `json:"cmd"`
    Data interface{} `json:"data"`
}

我还有一个名为CreateMessage的类型,定义如下:

type CreateMessage struct {
    Conf map[string]int `json:"conf"`
    Info map[string]int `json:"info"`
}

我有一个JSON字符串,内容如下:{"cmd":"create","data":{"conf":{"a":1},"info":{"b":2}}}

当我使用json.Unmarshal将其解码为一个Message变量时,得到的结果是{Cmd:create Data:map[conf:map[a:1] info:map[b:2]]}

所以,我能否将JSON解码为一个Message结构体,并根据Cmd将其Data字段的interface{}类型转换为CreateMessage类型?

我尝试直接将Data转换为CreateMessage类型,但编译器告诉我Data是一个map[string]interface{}类型。

英文:

I'm a newbie in Go and now I have a problem. I have a type called Message, it is a struct like this:

type Message struct {
    Cmd string `json:"cmd"`
    Data interface{} `json:"data"`
}

I also have a type called CreateMessage like this:

type CreateMessage struct {
    Conf map[string]int `json:"conf"`
    Info map[string]int `json:"info"`
}

And I have a JSON string like {"cmd":"create","data":{"conf":{"a":1},"info":{"b":2}}}.

When I use json.Unmarshal to decode that into a Message variable, the answer is {Cmd:create Data:map[conf:map[a:1] info:map[b:2]]}.

So could I decode the JSON into a Message struct and change its Data's interface{} to type CreateMessage according to the Cmd?

I tried to convert Data directly into type CreateMessage but the complier told me that Data is a map[sting]interface{} type.

答案1

得分: 42

为消息的固定部分定义一个结构类型,其中包含一个json.RawMessage字段来捕获消息的变体部分。为每个变体类型定义结构类型,并根据命令对它们进行解码。

type Message struct {
  Cmd  string          `json:"cmd"`
  Data json.RawMessage `json:"data"`
}

type CreateMessage struct {
  Conf map[string]int `json:"conf"`
  Info map[string]int `json:"info"`
}

func main() {
  var m Message
  if err := json.Unmarshal(data, &m); err != nil {
    log.Fatal(err)
  }
  switch m.Cmd {
  case "create":
    var cm CreateMessage
    if err := json.Unmarshal([]byte(m.Data), &cm); err != nil {
      log.Fatal(err)
    }
    fmt.Println(m.Cmd, cm.Conf, cm.Info)
  default:
    log.Fatal("bad command")
  }
}

playground示例

英文:

Define a struct type for the fixed part of the message with a json.RawMessage field to capture the variant part of the message. Define struct types for each of the variant types and decode to them based on the the command.

type Message struct {
  Cmd string `json:"cmd"`
  Data      json.RawMessage
}  

type CreateMessage struct {
    Conf map[string]int `json:"conf"`
    Info map[string]int `json:"info"`
}  

func main() {
    var m Message
    if err := json.Unmarshal(data, &m); err != nil {
        log.Fatal(err)
    }
    switch m.Cmd {
    case "create":
        var cm CreateMessage
        if err := json.Unmarshal([]byte(m.Data), &cm); err != nil {
            log.Fatal(err)
        }
        fmt.Println(m.Cmd, cm.Conf, cm.Info)
    default:
        log.Fatal("bad command")
    }
}

playground example

huangapple
  • 本文由 发表于 2015年2月1日 00:56:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/28254102.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定