Json 如何将结构编码回字节缓冲区

Json 如何将结构编码回字节缓冲区,json,go,Json,Go,我发出一个API请求,得到的响应是bytes.Buffer。 然后我将其解码到我的结构中: resp, status, err := // api call that calls http client do and returns byte buff result := MyStruct{} err = json.NewDecoder(response).Decode(&result) 我知道我想获取我的结构、结果和gzip 我应该使用json解码器获取值吗? 然后,我想获取解码后

我发出一个API请求,得到的响应是bytes.Buffer。 然后我将其解码到我的结构中:

resp, status, err := // api call that calls http client do and returns byte buff

result := MyStruct{}
err = json.NewDecoder(response).Decode(&result)
我知道我想获取我的结构、结果和gzip

我应该使用json解码器获取值吗?

然后,我想获取解码后的json,这样我最终就可以gzip它了


此外,我还混淆了字节数组、bytebuffer和这些读取器。这个层次结构像java吗?

我被你的问题弄糊涂了,但也许这有点帮助:

假设您使用的是标准HTTP,那么您的HTTP调用将通过
Client.Do
完成,它返回一个

您可以从类型为的
body
字段中读取响应正文。这实际上只是一个结合了and接口的接口。如果您知道响应是
json
,现在可以创建一个
json.Decoder
,使用它接受任何
io.Reader

重要的是要记住,所有类型都通过在其上定义以下函数来隐式实现
io.Reader

Read(p []byte) (n int, err error)
正如
*http.Response
Body
字段是一个
io.Reader
任何
字节。Buffer
实现
io.Reader
,因为它实现了该功能

相比之下,
[]字节(字节数组)是一种标量类型,它本身不实现任何功能。因此,
[]字节
不实现
io.Reader
,因此不能将其传递到
json.NewDecoder
。如果您想从字节数组/切片解码JSON,您可能只需要使用或从
[]字节创建
字节.Buffer
,然后再次将其传递给
JSON.Decoder


同样的概念也适用于将JSON编码回来,但这次不是使用
io.Reader
,而是使用
io.Writer
io.Reader
io.Writer
接口来指定对象行为,而不管其实现如何
bytes.Buffer
是实现
io.Reader
io.Writer
的数据结构。数组正是与其他语言相似的核心语言数据结构。大多数接口的优点是,不管底层实现如何,您都可以统一使用它们。例如,io库有
func-teereder(r-Reader,w-Writer)Reader
,它返回一个读卡器,该读卡器向w写入它从r读取的内容。您可以在读取和解码时使用它来生成gzip响应

SomeWriter, err := os.OpenFile("some/File", os.O_WRONLY, os.ModePerm ) //gzip to file for example
gzipper := gzip.NewWriter(SomeWriter) //but can be any Writer
tee := io.TeeReader(response, gzipper)
//and then
err = json.NewDecoder(tee).Decode(&result)

如果要将结构存储为json,最简单的方法通常是使用,如:

在这种情况下,b将是一个字节片([]字节)。这可以在以后使用
gzip
包进行gzip压缩。例如,要将字节gzip到文件中,可以使用:

f, _ := os.Create("/tmp/s.gz")
defer f.Close()

w := gzip.NewWriter(f)
w.Write(b)
w.Close()
如果愿意,可以直接使用来绕过创建字节片

f, _ := os.Create("/tmp/s.gz")
defer f.Close()

w := gzip.NewWriter(f)
json.NewEncoder(w).Encode(&myStruct)
w.Close()
根据要存储或发送gzip json的位置,可以将
gzip.NewWriter(f)
中使用的参数
f
替换为实现
io.Writer
的任何对象。例如,您可以在处理程序中直接使用
http.ResponseWriter
发送gzip响应:

func MyHandler(w http.ResponseWriter, r *http.Request) {
    myStruct := ...          // Get struct from somewhere
    gz := gzip.NewWriter(w)
    json.NewEncoder(gz).Encode(&myStruct)
    gz.Close()
}

如果您已经将所有数据设置为
[]字节
,那么我更喜欢使用
json.marshall
。如果您使用流式数据和/或您只有一个
io.Reader
,那么
json.Decoder
就是一个不错的选择。
func MyHandler(w http.ResponseWriter, r *http.Request) {
    myStruct := ...          // Get struct from somewhere
    gz := gzip.NewWriter(w)
    json.NewEncoder(gz).Encode(&myStruct)
    gz.Close()
}