How can I turn map[string]interface{} to different type of struct?

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

How can I turn map[string]interface{} to different type of struct?

问题

我正在调用一个API,它将返回如下的JSON对象:

{
  "name": "XXX",
  "type": "TYPE_1",
  "shared_fields": {...},
  "type_1_fields": {...},
  ..
  "type_2_fields": {...}
}

根据不同的类型,这个对象将具有不同类型的字段,但这些字段对于不同的类型是确定的。
因此,我将JSON字符串解组为map[string]interface{}以获取不同的类型,但是如何将这些map[string]interface{}转换为特定的结构体呢?

var f map[string]interface{}
err := json.Unmarshal(b, &f)
type := f["type"]
switch type {
  case "type_1":
    //初始化type_1的结构体
  case "type_2":
    //初始化type_2的结构体
}
英文:

I'm calling an API which will return Json objects like this:

{
  name: "XXX"
  type: "TYPE_1"
  shared_fields: {...}
  type_1_fields: {...}
  ..
  type_2_fields: {...}
}

Based on different types, this object will have different kinds of fields, but these fields are certain for different types.
So, I unmarshal the Json string to map[string]interface{} to fetch the the different type but how can I turn these map[string]interface{} to a certain struct?

  var f map[string]interface{}
  err := json.Unmarshal(b, &f)
  type := f["type"]
  switch type {
    case "type_1":
      //initialize struct of type_1
    case "type_2":
      //initialize struct of type_2
  }

答案1

得分: 2

对于这种两步骤的 JSON 解码,你可能想要查看 json.RawMessage。它允许你推迟处理 JSON 响应的某些部分。文档中的示例展示了如何使用它。

英文:

For this sort of two-step json decoding you will probably want to check out json.RawMessage. It allows you to defer processing of parts of your json response. The example in the docs shows how.

答案2

得分: 0

一种方法是使用一个构造函数(以New…开头)作为输入参数来接收一个映射。

第二种方法,我认为速度较慢,是重新将其解组为正确的结构类型。

英文:

One way to do it would be to have a constructor function (one that starts with New…) that takes a map as input parameter.

A second way, much slower in my opinion, would be to redo the unmarshalling to the right struct type.

答案3

得分: 0

如果类型差异很大,并且你想要懒一点,你可以尝试在每种格式中进行解码:

  f1 := type1{}
  err := json.Unmarshal(b, &f1)
  if err == nil {
      return f1
  }
  f2 := type2{}
  err := json.Unmarshal(b, &f2)
  if err == nil {
     return f2
  }
  ...

如果对象相似或者你想要更加细致,你可以先解码类型,然后再进行操作:

  type BasicInfo struct {
     Type string `json:"type"`
  }

  f := BasicInfo{}
  err := json.Unmarshal(b, &f)
  switch f.Type {
    case "type_1":
      //初始化 type_1 的结构体
    case "type_2":
      //初始化 type_2 的结构体
  }
英文:

If the types are different enough and you want to be lazy you can just try to decode it in each format:

  f1 := type1{}
  err := json.Unmarshal(b, &f1)
  if err == nil {
      return f1
  }
  f2 := type2{}
  err := json.Unmarshal(b, &f2)
  if err == nil {
     return f2
  }
  ...

If the objects are similar or you want to be less lazy, you could just decode the type and then do something:

  type BasicInfo struct {
     Type string `json:"type"`
  }

  f := BasicInfo{}
  err := json.Unmarshal(b, &f)
  switch f.Type {
    case "type_1":
      //initialize struct of type_1
    case "type_2":
      //initialize struct of type_2
  }

huangapple
  • 本文由 发表于 2014年8月8日 15:03:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/25197717.html
匿名

发表评论

匿名网友

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

确定