尝试编组此JSON时为什么Go出错?

时间:2016-04-24 01:11:37

标签: json go struct

我正在尝试使用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解析为您定义的结构。 任何不适合结构的字段都将被忽略。我们将首先介绍该选项。

这让我相信它并非如此。

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

2 个答案:

答案 0 :(得分:1)

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

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

如果将此与给定结构进行比较,则可以看到结构未对齐。您给定的Tracks结构具有一个Track s片段的字段。如果我将其转换为JSON,则表示为以下内容。

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

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

// 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
}

答案 1 :(得分:0)

Go类型的结构必须与JSON数据中的结构匹配。该应用程序缺少此JSON的粗体范围的嵌套级别:{“track”:{“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)
}