【问题标题】:Unmarshal only gives me first element of array that is nested in JSON responseUnmarshal 只给我嵌套在 JSON 响应中的数组的第一个元素
【发布时间】:2016-05-31 12:34:14
【问题描述】:

我正在尝试使用 Flickr API,并且我有一个端点可以给我这样的响应

{
  "photos": {
    "page": 1,
    "pages": 500,
    "perpage": 1,
    "total": 500,
    "photo": [
      {
        "id": "12345",
        "owner": "12345@N01",
        "secret": "12ab345xyz",
        "server": "1234",
        "farm": 1,
        "title": "Some Title",
        "ispublic": 1,
        "isfriend": 0,
        "isfamily": 0
      },
     ...
    ]
  },
  "stat": "ok"
}

我有一个看起来像这样的结构

type FlickrResp struct {
    Photos struct {
        Page int            `json:"page"`       //what page the results were retreived from
        Pages int           `json:"pages"`      //total number of pages of results
        Perpage int         `json:"perpage"`    //number of results per page
        Total int           `json:"total"`      //total number of results
        Photo []struct {
            ID string       `json:"id"`         //image ID
            Owner string    `json:"owner"`      //owner ID
            Secret string   `json:"secret"`     //owner secret
            Server string   `json:"server"`     //server ID
            Farm int        `json:"farm"`       //farm ID
            Title string    `json:"title"`      //image title
            Ispublic string `json:"ispublic"`   //is image publicly viewable?
            Isfriend string `json:"isfriend"`   //is image owner my friend?
            Isfamily string `json:"isfamily"`   //is image owner my family?
        }                   `json:"photo"`      //array of objects with details of photos
    }                       `json:"photos"`     //object that holds information about photoset
    Stat string             `json:"stat"`       //status
}

我正在尝试解组

var fr FlickrResp                                               //create blank struct of type FlickrResp to hold JSON
resp, err := ioutil.ReadAll(flickrCB.Body)                      //read HTTP GET response
if err != nil {

}
json.Unmarshal([]byte(resp), &fr)                               //serialize JSON into template

flickCB.Body 来自 http.Get

问题是我只得到照片数组的第一个元素。当我打印转换为字符串的响应对象时,我可以看到我有多个元素。我究竟做错了什么?几天来,我一直在反对 Unmarshal 和更复杂的 JSON 响应。

【问题讨论】:

  • 您是否正在阅读来自json.Unmarshal 的错误?当我尝试上述方法时,我遇到了ispublicisfriendisfamily 与结构所期望的字符串之间的类型不匹配的问题。如果我更改类型,它似乎可以正常工作。这是一个更改示例,包括 json.Number 的一个字段的用法,在这种情况下可以很方便 - play.golang.org/p/4fE_MkxgxS。我在结果中看到Photo 中有两个条目。
  • 做到了,谢谢。我不想谈论我经历了多少次。

标签: arrays json go unmarshalling flickr


【解决方案1】:

最初在 cmets 中回答,但需要更多说明:

json.Unmarshal 有一个未捕获的错误:

json: cannot unmarshal number into Go value of type string

由将ispublicisfriendisfamily 提供为整数的闪烁 API 之间的类型不匹配导致,但该结构需要字符串。一个简单的解决方法是将它们转换为整数。

这种情况的另一种选择是使用json.Number,它包装了来自源 json 的基本字符串,并提供了一些方便的方法来稍后将其转换为数字(或将其保留为字符串)。通过做说

Ispublic json.Number `json:"ispublic"`   //is image publicly viewable?
Isfriend json.Number `json:"isfriend"`   //is image owner my friend?
Isfamily json.Number `json:"isfamily"`

它可以正常工作,并且可以通过fr.Ispublic.String()轻松将结果作为字符串获取。

在这种情况下可能有用的更精细的更改是使用自定义布尔类型。有问题的值似乎反映了布尔值,但整数也不能干净地映射到布尔值。可以使用自定义反序列化类型。在stackoverflow的其他地方借用this example

type ConvertibleBoolean bool

func (bit ConvertibleBoolean) UnmarshalJSON(data []byte) error {
    asString := string(data)
    if asString == "1" || asString == "true" {
        bit = true
    } else if asString == "0" || asString == "false" {
        bit = false
    } else {
        return errors.New(fmt.Sprintf("Boolean unmarshal error: invalid input %s", asString))
    }
    return nil
}

以上内容可让您将 Is* 值声明为 ConvertibleBoolean,并自动将您可能在 Flickr 中获得的这些字段中的 0 和 1 值映射到布尔值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-14
    • 2023-03-21
    相关资源
    最近更新 更多