【问题标题】:Why does Go error when trying to marshal this JSON?为什么在尝试编组此 JSON 时 Go 会出错?
【发布时间】:2016-04-24 12:06:38
【问题描述】:

我正在尝试一个相当简单的示例,尝试使用 golang 将 JSON 文件解码为一些结构。但是,当我尝试得到错误时,

json: 无法将对象解组为 []main.Track

类型的 Go 值

我不明白。这是有问题的代码,JSON 可以是found here

package main

import (
    "encoding/json"
    "fmt"
    "net/http"
    "os"
)

// Tracks a group of Track types
type Tracks struct {
    Tracks []Track
}

// Track represents a singular track
type Track struct {
    Name   string
    URL    string
    Artist Artist
}

// Artist represents a single artist
type Artist struct {
    Name string
    MBID string
    URL  string
}

func main() {
    url := "http://ws.audioscrobbler.com/2.0/?method=geo.gettoptracks&api_key=c1572082105bd40d247836b5c1819623&format=json&country=Netherlands"
    response, err := http.Get(url)

    if err != nil {
        fmt.Printf("%s\n", err)
        os.Exit(1)
    }

    defer response.Body.Close()

    var tracks Tracks
    decodeErr := json.NewDecoder(response.Body).Decode(&tracks)

    if decodeErr != nil {
        fmt.Printf("%s\n", decodeErr)
        os.Exit(1)
    }

    for _, track := range tracks.Tracks {
        fmt.Printf("%s: %s\n", track.Artist.Name, track.Name)
    }
}

我最初的想法是,也许您需要使用结构对每个 JSON 值进行分类,但我没有这样做,但在阅读 this article 时说:

对此有两个答案。当您知道您的数据会是什么样子时,最简单的选择是将 JSON 解析为您定义的结构。 任何不适合结构的字段都将被忽略。我们将首先介绍该选项。

这让我相信事实并非如此。

在这种情况下我做错了什么?

【问题讨论】:

  • 如果您想避免此类问题,您可以尝试使用json-to-go tool。它基本上将 json 转换为类型定义。

标签: json go struct


【解决方案1】:

如果您查看对查询的响应的 JSON 结构,您会看到返回了具有 tracks 属性的单个对象。

{
    "tracks": {
        "track": [ {...} ]
    }
}

如果您将其与给定的结构进行比较,您会发现该结构没有对齐。你给定的Tracks 结构有一个字段是Tracks 的一部分。如果我将其转换为 JSON,它将表示为以下内容。

{ 
    "tracks": [ { ... } ]
}

这是您错误的根源。 JSON 解码器期望根 JSON 对象的 tracks 字段是一个数组。返回的是一个包含tracks 属性的对象,但它的值是另一个包含track 属性的JSON 对象,该属性 轨道数组。您可以更新您的结构以反映此架构,如下所示。

// A response object from the API
type Response struct {
    Tracks Tracks
}

// Tracks a group of Track types
type Tracks struct {
    Track []Track
}

// Track represents a singular track
type Track struct {
    Name   string
    URL    string
    Artist Artist
}

【讨论】:

    【解决方案2】:

    Go 类型的结构必须与 JSON 数据中的结构相匹配。应用程序缺少此 JSON 的粗体范围的嵌套级别:{"tracks":{"track":[{

    以下是更新类型以匹配 JSON 的方法:

    type Tracks struct {
        Tracks struct {
          Track []Track
        }
    }
    
    ...
    
    for _, track := range tracks.Tracks.Track {
        fmt.Printf("%s: %s\n", track.Artist.Name, track.Name)
    }
    

    【讨论】:

    • 您能再解释一下吗?我不确定我是否理解。
    • 我想我明白了,this answer 详细说明了一点,但这样做不是可选的吗(即:我使用两个外部结构来做它应该仍然有效)?跨度>
    猜你喜欢
    • 2013-08-14
    • 2012-05-02
    • 2013-03-07
    • 2021-05-01
    • 1970-01-01
    • 2012-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多