1

Writing my first Go Application I am learning to make a basic api call and parse the json response. I am pretty sure I am not casting my types correctly and my response is

false
  0
 0

  0
 0 false
 0

If I create a few arrays with data in them I can get that response but when I add this more complexed json response to the mix things get more confusing which leads me to be quite positive I am not casting correctly.

This is my current code after playing around and changing things in order to break stuff and try and figure things out.

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
) 
    type Payload struct {
        results Data 
}

    type Data struct {
        poster_path string
        adult bool
        overview string
        release_date string
        genre_ids int
        id int
        original_title string
        original_language string
        title string
        backdrop_path string
        popularity float64
        vote_count int
        video bool
        vote_average float64
}


type poster_path map[string]string
type adult map[string]bool
type overview map[string]string
type release_date map[string]string
type genre_ids map[string]int
type id map[string]int
type original_title map[string]string
type original_language map[string]string
type title map[string]string
type backdrop_path map[string]string
type popularity map[string]float64
type vote_count map[string]int
type video map[string]bool
type vote_average map[string]float64

func main() {
      // http://image.tmdb.org/t/p/w185
      url := "https://api.themoviedb.org/3/movie/top_rated?api_key=####APIKEYHERE######"
      res, err := http.Get(url)
      if err != nil {
        panic(err)
      }
      defer res.Body.Close()

      body, err := ioutil.ReadAll(res.Body)
      if err != nil {
        panic(err)
      }
      var p Payload

      err = json.Unmarshal(body, &p)
      if err != nil {
        panic(err)
      }

      fmt.Println(
        p.results.poster_path, "\n", p.results.adult,
        p.results.overview, "\n", p.results.release_date,
        p.results.genre_ids, "\n", p.results.id,
        p.results.original_title, "\n", p.results.original_language,
        p.results.title, "\n", p.results.backdrop_path,
        p.results.popularity, "\n", p.results.vote_count,
        p.results.video, "\n", p.results.vote_average,
        )
}

This is what the JSON response looks like,

{
    "page": 1,
    "results": [
        {
            "poster_path": "/lIv1QinFqz4dlp5U4lQ6HaiskOZ.jpg",
            "adult": false,
            "overview": "Under the direction of a ruthless instructor, a talented young drummer begins to pursue perfection at any cost, even his humanity.",
            "release_date": "2014-10-10",
            "genre_ids": [
                18,
                10402
            ],
            "id": 244786,
            "original_title": "Whiplash",
            "original_language": "en",
            "title": "Whiplash",
            "backdrop_path": "/6bbZ6XyvgfjhQwbplnUh1LSj1ky.jpg",
            "popularity": 9.685051,
            "vote_count": 1706,
            "video": false,
            "vote_average": 8.36
        }
}

A few things that stand out to me,

When I tried to cast the float I was confused about casting from float32 to float64

There is an array inside the json response which was confusing when trying to cast,

"genre_ids": [
                36,
                18,
                53,
                10752
            ], 
3
  • 1
    Possible duplicate of Converting Go struct to JSON Commented Mar 11, 2016 at 7:12
  • I genuinely don't mean this in a bad way, but all your type's... that's just horrible. Do you really need them? I mean: what's wrong with the occasional map[string]interface{}? You're basically declaring types that are maps, whereas (when dealing with json) a struct is just sooo much easier Commented Mar 11, 2016 at 18:23
  • Hey thank you for your feedback. I will take any criticism you may offer. This is the absolute first script I have written in Go. I watched a view tutorials and this is what I gained from them. I removed all those maps and it makes a lot more sense from Pie-o-Pah answer Commented Mar 11, 2016 at 22:27

2 Answers 2

4

Is a common beginners mistake. Due to language design, the encoding/json package can only unmarshal into exported fields.

From the encoding/json package:

To unmarshal JSON into a struct, Unmarshal matches incoming object keys to the keys used by Marshal (either the struct field name or its tag), preferring an exact match but also accepting a case-insensitive match. Unmarshal will only set exported fields of the struct.

To export a field, simply use a capital first letter of the name. Eg.:

type Payload struct {
    Results Data 
}

instead of

type Payload struct {
    results Data 
}
Sign up to request clarification or add additional context in comments.

7 Comments

Hey man thank you so much. That makes sense and helped. I am almost there. Would you mind taking a look at the types vs the type in the json and make sure I am casting correctly? Because I am getting this now go run request.go panic: json: cannot unmarshal array into Go value of type main.Data
@wuno Sure. The error is simple. "results" is an array of data objects (as the error says), but in Go you have defined Results as a simple Data object. Just change Results Data to Results []Data
So funny. Right before you answered me I found something talking about this. I am sure I am not casting correctly and when I make that change I still have a bunch of this now .Results.Backdrop_path undefined (type []Data has no field or method Backdrop_path)
@wuno: No. Results doesn't have any fields. Results is a slice. But Results[0].Backdrop_path will work .. given the JSON object contains at least one result object in the array.
Thanks man, I really appreciate you. I can loop through the array now but its still just printing out 0 and false. for i := 0; i < 10; i++ { fmt.Println( p.Results[i].poster_path, results in false 0 0 0 0 false 0 false 0 0 0 0 fals
|
1

First of all, you are missing a closing square bracket ] at the end of results in your JSON.

Secondly, you did not structure your structs according to the JSON you receive.

Lastly, use JSON tags after each exported field in your struct when dealing with Unmarshal/marshaling to help Go detect the appropriate fields (not necessary if you name the fields according to how Unmarshal/marshal identify fields.

type Payload struct {
        Page    int
        Results []Data 
}

type Data struct {
        PosterPath       string  `json:"poster_path"`
        Adult            bool    `json:"adult"`
        Overview         string  `json:"overview"`
        ReleaseDate      string  `json:"release_date"`
        GenreIds         []int   `json:"genre_ids"`
        Id               int     `json:"id"`
        OriginalTitle    string  `json:"original_title"`
        OriginalLanguage string  `json:"original_language"`
        Title            string  `json:"title"`
        BackdropPath     string  `json:"backdrop_path"`
        Popularity       float64 `json:"popularity"`
        VoteCount        int     `json:"vote_count"`
        Video            bool    `json:"video"`
        VoteAverage      float64 `json:"vote_average"`
}

Note that GenreIds has to be []int to match the JSON data as well. And it's a good idea not to use CamelCase in Go.

See https://play.golang.org/p/VduPD9AY84

4 Comments

Note that you do not need struct tags: you use them when the JSON key names do not match your Go struct field names.
@elithrar thanks it's a safeguard since wuno's few original field names don't match the JSON.
I know; I'm being a pedant and saying that "always use JSON tags" is not entirely correct. It's important for the OP to know when you would use them; the real problem was the unexported struct fields.
@elithrar you are right. Edited as per your comment!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.