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
suscipit recusandae consequuntur expedita et cum
reprehenderit molestiae ut ut quas totam
nostrum 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
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
", 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 ", 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.
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