Reputation: 29326
I'm trying a rather simple example of trying to decode a JSON file into some structs using golang. However, when attempting to I get the error that
json: cannot unmarshal object into Go value of type []main.Track
Which I don't understand. Here's the code in question, and the JSON can be 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)
}
}
My initial thought was maybe you need to categorize every single JSON value with structs, which I didn't do, but upon reading this article which says:
There are two answers to this. The easy option, for when you know what your data will look like, is to parse the JSON into a struct you’ve defined. Any field which doesn’t fit in the struct will just be ignored. We’ll cover that option first.
Which leads me to believe that it isn't that.
What am I doing wrong in this scenario?
Upvotes: 1
Views: 2120
Reputation: 121029
The structure of the Go types must match the structure in the JSON data. The application is missing a level of nesting for the bolded range of this JSON: {"tracks":{"track":[{
Here's how to update the types to match the JSON:
type Tracks struct {
Tracks struct {
Track []Track
}
}
...
for _, track := range tracks.Tracks.Track {
fmt.Printf("%s: %s\n", track.Artist.Name, track.Name)
}
Upvotes: 0
Reputation: 4678
If you look at the JSON structure of the response to your query you'll see that a single object with a tracks
property is returned.
{
"tracks": {
"track": [ {...} ]
}
}
If you compare this to to the given structs you can see that the structure does not align. Your given Tracks
struct has a field that is a slice of Track
s. If I were to cast this as JSON it would be represented as the following.
{
"tracks": [ { ... } ]
}
This is the root of your error. The JSON decoder is expecting the tracks
field of the root JSON object to be an array. What is returned is an object that contains the tracks
property but its values is another JSON object which contains the track
property which is the array of tracks. You could update your structures to reflect this schema as follows.
// 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
}
Upvotes: 1