Sion Sion - 1 year ago 148
JSON Question

Decoding gZip json with Go

As a Go newbie it's difficult for me to pinpoint the problem area, but hopefully giving you some facts will help.

I'm playing with an API which returns its

as gzip. I have written the following to encode my response struct:

reader, err = gzip.NewReader(resp.Body)
defer reader.Close()

// print to standard out
//_, err = io.Copy(os.Stdout, reader)
//if err != nil {
// log.Fatal(err)

// Decode the response into our tescoResponse struct
var response TescoResponse
err := json.NewDecoder(reader).Decode(&response)

I've removed the error handling for brevity, but the point of interest is that if I uncomment the print to stdout, I get the expected result. However, the decode doesn't give me what I expect. Any pointers? Is it that the struct has to map exactly to the response??

Here's the full example:

Answer Source

From the documenation:

DisableCompression, if true, prevents the Transport from requesting compression with an "Accept-Encoding: gzip" request header when the Request contains no existing Accept-Encoding value. If the Transport requests gzip on its own and gets a gzipped response, it's transparently decoded in the Response.Body. However, if the user explicitly requested gzip it is not automatically uncompressed.

Proposed solution:

type gzreadCloser struct {

func (gz gzreadCloser) Close() error {
    return gz.Closer.Close()

// then in your http call ....

    if resp.Header.Get("Content-Encoding") == "gzip" {
        zr, err := gzip.NewReader(resp.Body)
        if err != nil {
            return nil, err
        resp.Body = gzreadCloser{zr, resp.Body}

// then you will be able to decode the json transparently

if err := json.NewDecoder(resp.Body).Decode(&response); err != nil {


Adapted solution from your code:

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download