1

I'm trying to consume JSON apis through golang, but having a terrible time getting the response back. I'm using a sample JSON endpoint http://jsonplaceholder.typicode.com/posts/1 that returns

{
  "userId": 1,
  "id": 1,
  "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
  "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
}

This is my code which comes from this Stack Overflow Answer:

package main

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

type Post struct {
    UserID string
    ID string
    Title string
    Body string
}

func getJson(url string, target interface{}) error {
    r, err := http.Get(url)
    if err != nil {
        return err
    }
    defer r.Body.Close()
    fmt.Println(r)
    return json.NewDecoder(r.Body).Decode(target)
}

func main() {
    post := new(Post) // or &Foo{}
    getJson("http://jsonplaceholder.typicode.com/posts/1", &post)
    println(post.Body)

}

And this is the output:

go run main.go 
&{200 OK 200 HTTP/1.1 1 1 map[Cf-Cache-Status:[HIT] Cf-Ray:[2bf857d2e55e0d91-SJC] Access-Control-Allow-Credentials:[true] Cache-Control:[public, max-age=14400] Expires:[Sat, 09 Jul 2016 06:28:31 GMT] X-Content-Type-Options:[nosniff] Server:[cloudflare-nginx] Date:[Sat, 09 Jul 2016 02:28:31 GMT] Connection:[keep-alive] X-Powered-By:[Express] Etag:[W/"124-yv65LoT2uMHrpn06wNpAcQ"] Content-Type:[application/json; charset=utf-8] Set-Cookie:[__cfduid=d0c4aacaa5db8dc73c59a530f3d7532af1468031311; expires=Sun, 09-Jul-17 02:28:31 GMT; path=/; domain=.typicode.com; HttpOnly] Pragma:[no-cache] Via:[1.1 vegur] Vary:[Accept-Encoding]] 0xc8200ee100 -1 [chunked] false map[] 0xc8200da000 <nil>}

I know the endpoint works. Is this an encoding issue or something else? I'm on Mac OSX 10.11.15.

Thanks

2 Answers 2

3

You have error in unmarshal: cannot unmarshal number into Go value of type string if you print error. UserId and Id should be int.

Please don't ignore error!

try this code:

package main

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

type Post struct {
    UserID int
    ID     int
    Title  string
    Body   string
}

func getJson(url string, target interface{}) error {
    r, err := http.Get(url)
    if err != nil {
        return err
    }
    defer r.Body.Close()
    fmt.Println(r)
    return json.NewDecoder(r.Body).Decode(target)
}

func main() {
    post := new(Post) // or &Foo{}
    err := getJson("http://jsonplaceholder.typicode.com/posts/1", &post)
    if err != nil {
        panic(err)
    }

    println(post.Body)
    fmt.Printf("Post: %+v\n", post)
}

Edited: Why can't I print out the contents of the response body and see it in the command line? Is it encoded? Ans: HTTP request or response used to be in a format or encoded defined by the response-header fields.

The response-body is obtained from the message-body by decoding any Transfer-Encoding that might have been applied to ensure safe and proper transfer of the message.

If you print: fmt.Println("Header: %#v\n", r.Header)
You will see, Content-Type:[application/json; charset=utf-8] That's why you are decoding with Json. It also could be xml.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. Super helpful. Quick follow up question: why can't I print out the contents of the response body and see it in the command line? Is it encoded?
0

maybe you should try this:

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
)   

type Result struct {
    UserID int    `json:"userId"`
    ID     int    `json:"id"`
    Title  string `json:"title"`
    Body   string `json:"body"`
}   

func main() {

    url := "http://jsonplaceholder.typicode.com/posts/1"

    req, _ := http.NewRequest("GET", url, nil)

    res, _ := http.DefaultClient.Do(req)

    defer res.Body.Close()
    body, _ := ioutil.ReadAll(res.Body)

    var result Result
    err := json.Unmarshal(body, &result)
    if err != nil {
        fmt.Println(err)
    }   

    fmt.Println(res)
    fmt.Println(string(body))

    fmt.Println(result)
    //fmt.Println(result.Title)
    //fmt.Println(result.Body)
}

You will get a Result struct

1 Comment

I actually thought this was a joke making fun of ignoring errors :)

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.