从强制HTTP解组JSON:查找值开头的无效字符

从强制HTTP解组JSON:查找值开头的无效字符,json,http,go,deflate,Json,Http,Go,Deflate,我刚刚编写了我的第一个Go应用程序,它通过http下载并解压简单的JSON对象。Http内容被压缩: 'content-encoding':'deflate' 我使用了几个著名的例子(如)。不幸的是,应用程序无法解析所需的JSON,出现了非常罕见和奇怪的错误。我没能找出问题所在。任何帮助都将不胜感激 JSON输入 (Python用于调试) 源代码(根据答案更新) 错误 [vitaly@thermaltake elliptics-manager]$ go run main.go &{20

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

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

JSON输入 (Python用于调试)

源代码根据答案更新)

错误

[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
[vitaly@thermaltakeelliptics manager]$go运行main.go
&{200 OK 200 HTTP/1.1 1 1映射[内容类型:[application/json]内容长度:[111]内容编码:[deflate]]0xc20803e340 111[]真映射[]0xc208028820}
[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]
死机:查找值开头的无效字符“x”

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

我不知道“x”,但结构字段必须是公共的(以大写字母开头),json解组器才会考虑。当然,名称与json键不匹配,您必须添加json注释,如下所示:

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

我不知道“x”,但结构字段必须是公共的(以大写字母开头),json解组器才会考虑。当然,名称与json键不匹配,您必须添加json注释,如下所示:

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

我相信这是由于你的双重编码
ioutil.ReadAll(res.Body)
返回一个
[]字节
,因此当您执行
[]字节(Body)
时,您正在强制转换已经是字节数组的内容,我猜第一个字节的UTF值是
x
。只要更新这个
json.Unmarshal([]字节(正文)和jsondata)
json.Unmarshal(正文和jsondata)
我打赌它会很好地解组

另外,与您的错误无关,但正如另一个答案中指出的,如果您不导出结构中的字段(在go中,这意味着以大写字母开头字段名),则解组器将无法使用它们。要使其正常工作,您需要将键入的内容更新为

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

之所以需要json注释,是因为解组器非常严格,需要字段名的精确匹配(区分大小写)。

我认为这是由于您使用了双重编码
ioutil.ReadAll(res.Body)
返回一个
[]字节
,因此当您执行
[]字节(Body)
时,您正在强制转换已经是字节数组的内容,我猜第一个字节的UTF值是
x
。只要更新这个
json.Unmarshal([]字节(正文)和jsondata)
json.Unmarshal(正文和jsondata)
我打赌它会很好地解组

另外,与您的错误无关,但正如另一个答案中指出的,如果您不导出结构中的字段(在go中,这意味着以大写字母开头字段名),则解组器将无法使用它们。要使其正常工作,您需要将键入的内容更新为

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

之所以需要json注释,是因为解组器非常严格,需要字段名的精确匹配(区分大小写)。

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


我猜PythonHTTP客户机会自动解压缩压缩后的字节,而GoHTTP客户机不会(我知道它对gzip是这样做的,但不确定是否对deflate是这样)。在您能够使用JSON封送器解析它们之前,您必须读取已缩减的字节并将其转换为unicode字符串

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

我猜PythonHTTP客户机会自动解压缩压缩后的字节,而GoHTTP客户机不会(我知道它对gzip是这样做的,但不确定是否对deflate是这样)。在您能够使用JSON封送器解析它们之前,您必须读取已缩减的字节并将其转换为unicode字符串

请试试这个

func get_content() {

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

    res, err := http.Get(url)
    if err != nil {
        panic(err.Error())
    }
    defer res.Body.Close()

    fmt.Println("res body:", res.Body)

    body, err := ioutil.ReadAll(resp=.Body)

    fmt.Println("body:", body)
    re, err := zlib.NewReader(bytes.NewReader(body))
    fmt.Println("zlib:", re)
    enflated, err := ioutil.ReadAll(re)
    fmt.Println("enflated:", string(enflated))

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

    fmt.Println(jsondata)
}
并确保
http://172.17.0.31:20000/top
返回json类型。

请尝试此操作

func get_content() {

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

    res, err := http.Get(url)
    if err != nil {
        panic(err.Error())
    }
    defer res.Body.Close()

    fmt.Println("res body:", res.Body)

    body, err := ioutil.ReadAll(resp=.Body)

    fmt.Println("body:", body)
    re, err := zlib.NewReader(bytes.NewReader(body))
    fmt.Println("zlib:", re)
    enflated, err := ioutil.ReadAll(re)
    fmt.Println("enflated:", string(enflated))

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

    fmt.Println(jsondata)
}

并确保
http://172.17.0.31:20000/top
返回json类型。

感谢您的及时回复和非常有用的解释(代码已更新)。但不幸的是,我再次面临同样的错误..解包器不区分大小写。将[]字节转换为[]字节不是必需的,但无害。感谢您的及时回复和非常有用的解释(代码已更新)。但不幸的是,我再次面临同样的错误..解包器不区分大小写。将[]字节转换为[]字节不是必需的,但无害。谢谢你的建议。我已经修复了
Top struct
,但不幸的是仍然存在相同的问题。您可以粘贴点击该url的原始输出吗?谢谢您的建议。我已经修复了
顶部结构
,但不幸的是仍然存在相同的问题can