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

解组具有多种值类型和任意数量键的 JSON

解组具有多种值类型和任意数量键的 JSON

Go
慕码人8056858 2022-11-23 15:52:19

我正在尝试读取具有以下形式的 JSON


{

  string: int,

  string: string,

  string: MyStruct,

  string: MyStruct,

  ...

  string: MyStruct,

}

例如


{

  "status": 200,

  "message": "some cool text",

  "coolKeyA": {

    "name": "yoda",

    "age": 900

   },

  "CoolKeyB": {

    "name": "Mahalalel",

    "age": 895

   },

   "CoolKeyC": {

    "name": "Prince",

    "age": 57

   },

}

期望的结果是获得 的地图map[string]MyStruct。有弹性或任意数量的“CoolKeyX”键,但其他键是静态的,例如状态和消息。


由于 JSON 中的值是不同的类型,我试图将它们放入空白map[string]interface{}中。然后目标是遍历键并取出它们感兴趣的键并将键转换map[string]inferface{string: string, string: int}为 MyStruct。


scaryAcceptAll := map[string]interface{}{}

  if err = json.Unmarshal(byteArray, &scaryAcceptAll); err != nil { 

    log.Printf("error: %v", err)

    return err 

  } 

  

  for k,v := range scaryAcceptAll { 

    if (k == "val0" ) || (k == "val1") {

        continue

    }   

    desiredMap[k] = models.MyStruct{Name: v["name"], Age: v["age"]}

  }

这给了我以下错误:NonIndexableOperand: invalid operation: cannot index v (variable of type interface{})


我知道解组 JSON 的基本思想是创建一个看起来像 json 的结构并使用它但是因为我不知道键的确切数量或“CoolKey”键的真正含义(因为它是一个包含哈希的字符串“000ab8f26d”)我不知道怎么做。我知道接口有点像包罗万象,但我不确定如何从中提取我想要的数据。


查看完整描述

1 回答

?
DIEA

TA贡献1537条经验 获得超2个赞

一种方法是实施自定义json.Unmarshaler

type Obj struct {

    Status   int

    Message  string

    CoolKeys map[string]Person

}


type Person struct {

    Name string

    Age  int

}

func (o *Obj) UnmarshalJSON(data []byte) error {

    // first, unmarshal the object into a map of raw json

    var m map[string]json.RawMessage

    if err := json.Unmarshal(data, &m); err != nil {

        return err

    }


    // next, unmarshal the status and message fields, and any

    // other fields that don't belong to the "CoolKey" group

    if err := json.Unmarshal(m["status"], &o.Status); err != nil {

        return err

    }

    delete(m, "status") // make sure to delete it from the map

    if err := json.Unmarshal(m["message"], &o.Message); err != nil {

        return err

    }

    delete(m, "message") // make sure to delete it from the map


    // finally, unmarshal the rest of the map's content

    o.CoolKeys = make(map[string]Person)

    for k, v := range m {

        var p Person

        if err := json.Unmarshal(v, &p); err != nil {

            return err

        }

        o.CoolKeys[k] = p

    }

    return nil

}

https://go.dev/play/p/s4YCmve-pnz


查看完整回答
反对 回复 2022-11-23

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信