douchuang1861 2017-11-01 20:24
浏览 220
已采纳

无法将字符串解组到Go结构字段中

I have the following (incomplete type) (which is a response from docker API from manifests endpoint v2 schema 1 https://docs.docker.com/registry/spec/manifest-v2-1/)

type ManifestResponse struct {
    Name         string `json:"name"`
    Tag          string `json:"tag"`
    Architecture string `json:"architecture"`

    FsLayers []struct {
        BlobSum string `json:"blobSum"`
    } `json:"fsLayers"`

    History []struct {
        V1Compatibility struct {
            ID              string `json:"id"`
            Parent          string `json:"parent"`
            Created         string `json:"created"`
        } `json:"v1Compatibility"`
    } `json:"history"`
}

While getting the following response:

 { "schemaVersion": 1,
   "name": "library/redis",
   "tag": "latest",
   "architecture": "amd64",
   "history": [
      {
         "v1Compatibility": "{\"id\":\"ef8a93741134ad37c834c32836aefbd455ad4aa4d1b6a6402e4186dfc1feeb88\",\"parent\":\"9c8b347e3807201285053a5413109b4235cca7d0b35e7e6b36554995cfd59820\",\"created\":\"2017-10-10T02:53:19.011435683Z\"}"
      }
   ]
}

While trying to deserialize it using the following snippet of code:

var jsonManResp ManifestResponse                                                                                                                                                                                                                                                
if err = json.NewDecoder(res.Body).Decode(&jsonManResp); err != nil {
    log.Fatal(err)
}

I get the following error:

json: cannot unmarshal string into Go struct field .v1Compatibility of type struct { ID string "json:\"id\""; Parent string "json:\"parent\""; Created string "json:\"created\"" }

Full playground code: https://play.golang.org/p/tHzf9GphWX

What might be the problem?

  • 写回答

1条回答 默认 最新

  • dryb38654 2017-11-01 20:26
    关注

    The problem is that v1Compatibility is a string value in the JSON; the value happens to be JSON content, but it's inside a JSON string, so can't be unmarshalled all in one step. You could instead unmarshal it in two passes:

    type ManifestResponse struct {
        Name         string `json:"name"`
        Tag          string `json:"tag"`
        Architecture string `json:"architecture"`
    
        FsLayers []struct {
            BlobSum string `json:"blobSum"`
        } `json:"fsLayers"`
    
        History []struct {
            V1CompatibilityRaw string `json:"v1Compatibility"`
            V1Compatibility V1Compatibility
        } `json:"history"`
    }
    
    type V1Compatibility struct {
        ID              string `json:"id"`
        Parent          string `json:"parent"`
        Created         string `json:"created"`
    }
    

    And then:

    var jsonManResp ManifestResponse
    if err := json.Unmarshal([]byte(exemplar), &jsonManResp); err != nil {
        log.Fatal(err)
    }
    for i := range jsonManResp.History {
        var comp V1Compatibility
        if err := json.Unmarshal([]byte(jsonManResp.History[i].V1CompatibilityRaw), &comp); err != nil {
            log.Fatal(err)
        }
        jsonManResp.History[i].V1Compatibility = comp
    }
    

    Working playground example here: https://play.golang.org/p/QNsu5_63E0

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 用泊松逆高斯分布拟合已知数据
  • ¥15 web课程,怎么做啊😭没好好听课 根本不知道怎么下手
  • ¥15 做一个关于单片机的比较难的代码,然后搞一个PPT进行解释
  • ¥15 python提取.csv文件中的链接会经常出现爬取失败
  • ¥15 数据结构中的数组地址问题
  • ¥15 maya的mel里,怎样先选择模型A,然后利用mel脚本自动选择有相同名字的模型B呢。
  • ¥15 Python题,根本不会啊
  • ¥15 会会信号与系统和python的来
  • ¥15 关于#python#的问题
  • ¥20 oracle RAC 怎么配置啊,配置