【问题标题】:Unmarshal nested JSON into flat struct in Go [duplicate]在 Go 中将嵌套的 JSON 解组为平面结构 [重复]
【发布时间】:2018-11-20 01:10:27
【问题描述】:

假设我定义一个结构如下:

type User struct {
    ID          string
    Name        string
    Age         uint
    City        string      `json:"address.city"`
    Province    string      `json:"address.province"`
}

我可以采用一个用户结构,并将扁平化的恶魔扩展成一个嵌套的 JSON 结构,并带有一个地址对象。然而,我正在努力朝着另一个方向前进。

我将如何获取以下 JSON:

{
    "ID": "1",
    "Name": "Keith Baldwin",
    "Age": 30,
    "address": {
        "city": "Saskatoon",
        "province": "Saskatchewan"
    }
}

然后将其解组到给定的结构中?

我是否缺少某些东西,或者我只能从头开始编写它,可能使用反射?

谢谢

【问题讨论】:

    标签: json go marshalling unmarshalling


    【解决方案1】:

    创建用户信息类

    type UserInfo struct {
        ID      string `json:"ID"`
        Name    string `json:"Name"`
        Age     int    `json:"Age"`
        Address struct {
            City     string `json:"city"`
            Province string `json:"province"`
        } `json:"address"`
    }
    

    然后将你的 json 数据解组到一个 userinfo 对象中

    var userInfo UserInfo
        jsonStr := `{
        "ID": "1",
        "Name": "Keith Baldwin",
        "Age": 30,
        "address": {
            "city": "Saskatoon",
            "province": "Saskatchewan"
        }
    }`
    json.Unmarshal([]byte(jsonStr), &userInfo)
    

    【讨论】:

    • 这是 @Ehsan.Saradar 解释的 Go-playground 示例:play.golang.org/p/Bn_zAsF75JV
    • 感谢您的来信。不幸的是,这对我不起作用,因为我需要能够对任何任意数据结构执行此操作,并且只能将结构中定义为 json:"something.something" 的字段展平。
    【解决方案2】:

    我认为您需要创建另一个 Address 结构。

    type Address struct {
        City     string `json:"city"`
        Province string `json:"province"`
    }
    
    type User struct {
        ID      string  `json:"id"`
        Name    string  `json:"name"`
        Age     uint    `json:"age"`
        Address Address `json:"address"`
    }
    

    【讨论】:

      【解决方案3】:

      您可以创建一个临时结构类型来将该数据转储为与您期望的格式匹配的格式。例如

      type userData struct {
          ID          string
          Name        string
          Age         uint
          address     map[string]string
      }
      

      虽然我最喜欢做的是将所有 json 转储到一个带有字符串键和 json.RawMessage 作为值的映射中。这将允许您将所有 json 解组到此映射中,然后根据需要解组每个单独的字段。

      var allData map[string]json.RawMessage
      var user User{}
      //Assuming we first get our json from a request, otherwise use json.Unmarshal(jsonData, &allData)
      err := json.NewDecoder(r.Body).Decode(&allData)
      if err != nil {
          //handle
      }
      err = json.Unmarshal(allData["ID"], &c.ID)
      if err != nil {
          //handle
      }
      var addressMap map[string]string
      err = json.Unmarshal(allData["address"], addressMap)
      if err != nil {
          //handle
      }
      c.City = addressMap["city"]
      c.Province = addressMap["province"]
      

      我没有测试过任何代码,所以它可能会出错,但这只是为了传达将所有数据转换为 json.RawMessage 值映射然后解组每个属性的想法。通常,您将进行更多错误检查以查看值是否存在等。当然,这需要更多工作,但它非常灵活,并且为您提供了对数据处理方式的大量可见性和能力,而不仅仅是解组一个结构并希望魔法起作用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-11-29
        • 2015-02-01
        • 2016-03-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-21
        相关资源
        最近更新 更多