简体   繁体   English

用Go解码gZip json

[英]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. 作为Go新手,我很难确定问题区域,但希望能给你一些事实会有所帮助。

I'm playing with an API which returns its Content-Encoding as gzip. 我正在使用API​​将其Content-Encoding作为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. 为简洁起见,我删除了错误处理,但感兴趣的是,如果我将打印取消注释到stdout,我会得到预期的结果。 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: https://play.golang.org/p/4eCuXxXm3T 以下是完整示例: https//play.golang.org/p/4eCuXxXm3T

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. DisableCompression,如果为true,则当请求不包含现有的Accept-Encoding值时,阻止传输使用“Accept-Encoding:gzip”请求标头请求压缩。 If the Transport requests gzip on its own and gets a gzipped response, it's transparently decoded in the Response.Body. 如果传输单独请求gzip并获得一个gzip压缩响应,它将在Response.Body中透明地解码。 However, if the user explicitly requested gzip it is not automatically uncompressed. 但是,如果用户明确请求gzip,则不会自动解压缩。

Proposed solution: 建议的解决方案:

type gzreadCloser struct {
    *gzip.Reader
    io.Closer
}

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

// then in your http call .... //然后在你的http电话....

    if resp.Header.Get("Content-Encoding") == "gzip" {
        resp.Header.Del("Content-Length")
        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: https://play.golang.org/p/Vt07y_xgak 来自您的代码的改编解决方案: https//play.golang.org/p/Vt07y_xgak

As @icza mentioned in the comments, decoding isn't required because the gzip reader automatically decodes when you read using it. 正如@icza在评论中提到的那样,不需要解码,因为gzip阅读器在您使用它时会自动解码。 Perhaps try: 也许试试:

ubs := make([]byte, len) // check Content-Length header to set len
n, err := reader.Read(ubs)
err := json.Unmarshal(ubs, &response)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM