json - 从压缩的 HTTP : invalid character looking for beginning of value 中解码 JSON

标签 json http go deflate

我刚刚编写了我的第一个 Go 应用程序,它通过 http 下载和解码简单的 JSON 对象。 Http 内容被压缩: 'content-encoding': 'deflate'

我使用了几个著名的例子(比如 this )。不幸的是,应用程序无法解析所需的 JSON,并出现非常罕见且奇怪的错误。我无法找出问题所在。任何帮助将不胜感激。

JSON 输入 (使用Python调试)

In [8]: r = requests.get("http://172.17.0.31:20000/top")

In [9]: r.text
Out[9]: u'{"timestamp":{"tv_sec":1428447555,"tv_usec":600186},"string_timestamp":"2015-04-07 22:59:15.600186","monitor_status":"enabled"}'
In [18]: r.headers
Out[18]: {'content-length': '111', 'content-type': 'application/json', 'connection': 'close', 'content-encoding': 'deflate'}

源代码(根据答案更新)

package main

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

type Top struct {
    Timestamp        Timestamp `json:"timestamp"`
    String_timestamp string    `json:"string_timestamp"`
    Monitor_status   string    `json:"monitor_status"`
}

type Timestamp struct {
    Tv_sec  int `json:"tv_sec"`
    Tv_usec int `json:"tv_usec"`
}

func get_content() {

    url := "http://172.17.0.31:20000/top"

    res, err := http.Get(url)
    if err != nil {
        panic(err.Error())
    }
    fmt.Println(res)

    body, err := ioutil.ReadAll(res.Body)
    if err != nil {
        panic(err.Error())
    }
    fmt.Println(body)

    var jsondata Top
    err = json.Unmarshal(body, &jsondata)
    if err != nil {
        panic(err.Error())
    }

    fmt.Println(jsondata)
}

func main() {
    get_content()
}

错误

[vitaly@thermaltake elliptics-manager]$ go run main.go 
&{200 OK 200 HTTP/1.1 1 1 map[Content-Type:[application/json] Content-Length:[111] Content-Encoding:[deflate]] 0xc20803e340 111 [] true map[] 0xc208028820 <nil>}
[120 156 77 203 65 14 130 48 16 70 225 171 152 127 93 76 59 51 162 244 50 13 96 99 154 216 98 232 192 134 112 119 81 55 110 95 190 183 65 83 142 85 251 252 130 223 160 107 168 113 132 119 66 55 145 182 117 108 62 109 249 70 98 234 108 183 27 84 157 83 121 132 191 19 100 221 165 177 210 216 235 137 200 11 123 230 243 207 195 32 79 37 233 52 135 3 235 82 15 29 75 63 60 227 29 251 27 195 90 38 189]
panic: invalid character 'x' looking for beginning of value

UPD:谢谢大家。现在很明显,这个问题的原因是 HTTP 响应的 deflate 压缩。然而,目前还不清楚如何在 Golang 中执行解压(参见 here )。

最佳答案

Go JSON 编码器只能编码 unicode 字符串。看来您的 JSON 不是用 unicode 编码的,而是用其他编码(deflate?)编码的。

如果您采用字节流:

[120 156 77 203 65 14 130 48 16 70 225 171 152 127 93 76 59 51 162 244 50 13 96 99 154 216 98 232 192 134 112 119 81 55 110 95 190 183 65 83 142 85 251 252 130 223 160 107 168 113 132 119 66 55 145 182 117 108 62 109 249 70 98 234 108 183 27 84 157 83 121 132 191 19 100 221 165 177 210 216 235 137 200 11 123 230 243 207 195 32 79 37 233 52 135 3 235 82 15 29 75 63 60 227 29 251 27 195 90 38 189]

并尝试从中获取一个 unicode 字符串:

body := []byte{120, 156, 77, 203, 65, 14, 130, 48, 16, 70, 225, 171, 152, 127, 93, 76, 59, 51, 162, 244, 50, 13, 96, 99, 154, 216, 98, 232, 192, 134, 112, 119, 81, 55, 110, 95, 190, 183, 65, 83, 142, 85, 251, 252, 130, 223, 160, 107, 168, 113, 132, 119, 66, 55, 145, 182, 117, 108, 62, 109, 249, 70, 98, 234, 108, 183, 27, 84, 157, 83, 121, 132, 191, 19, 100, 221, 165, 177, 210, 216, 235, 137, 200, 11, 123, 230, 243, 207, 195, 32, 79, 37, 233, 52, 135, 3, 235, 82, 15, 29, 75, 63, 60, 227, 29, 251, 27, 195, 90, 38, 189}
fmt.Println(string(body))

您会在控制台中看到一个奇怪的(压缩的?)字符串,而不是 JSON。

我猜想 python http 客户端会自动解压缩压缩后的字节,而 Go http 客户端不会(我知道它对 gzip 会这样做,但不确定是否会压缩压缩)。在您能够使用 JSON 编码器解析它们之前,您必须读出压缩的字节并将它们转换为 unicode 字符串。

关于json - 从压缩的 HTTP : invalid character looking for beginning of value 中解码 JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29502917/

相关文章:

json - Alamofire 使用 Struct 解码 JSON 响应时出错

http - Pragma 和 Cache-Control header 之间的区别?

python - 具有延迟的 HTTP 客户端异步调用

go - 依赖代码中未引用的模块(特别是 mockgen)的惯用方法是什么?

javascript - 为什么mockjax 向我的Ajax 消费者返回更改后的响应?

javascript - 正确检查javascript中的空值

ios - 如何检查 connectionDidFinishLoading 何时完成

java - Jersey 长时间运行请求超时

go - 使用 Gorilla Mux 和标准 http.FileServer 的自定义 404

logging - Fluentd + golang 日志记录应用程序出错