【发布时间】:2019-07-11 18:00:41
【问题描述】:
我有一个 []byte 类型的 JSON 对象,它是使用 json.Marshal 从结构创建的。我想在将 JSON 发布到我的端点之前对其进行 GZip。以下方法不起作用:
gz := gzip.NewWriter(myJSON)
因为[]byte 没有实现io.Writer。
一旦我已经创建了我的 JSON,是否有一些非常简单的方法可以做到这一点?
【问题讨论】:
我有一个 []byte 类型的 JSON 对象,它是使用 json.Marshal 从结构创建的。我想在将 JSON 发布到我的端点之前对其进行 GZip。以下方法不起作用:
gz := gzip.NewWriter(myJSON)
因为[]byte 没有实现io.Writer。
一旦我已经创建了我的 JSON,是否有一些非常简单的方法可以做到这一点?
【问题讨论】:
压缩到缓冲区并发布该缓冲区。
var buf bytes.Buffer
gz := gzip.NewWriter(&buf)
gz.Write(myJSON)
gz.Close()
因为*bytes.Buffer统计了io.Reader接口,所以创建请求时可以直接使用缓冲区。
req, err := http.NewRequest("POST", url, &buf)
if err != nil {
// handle error
}
req.Header.Set("Content-Encoding", "gzip")
req.Header.Set("Content-Type", "application/json; charset=utf-8")
【讨论】:
最好的选择是将您的 JSON 编组流式传输到您的 gzip 编写器:
func compressJSON(w io.Writer, i interface{}) error {
gz := gzip.NewWriter(w)
if err := json.NewEncoder(gz).Encode(i); err != nil {
return err
}
return gz.Close()
}
这样做的好处是不会暂时在内存中缓冲你的 json,所以它会更快并且使用更少的 RAM。
如果您需要将其作为io.Reader,例如用于 HTTP 请求的正文,您可以使用管道进行转换:
r, w := io.Pipe()
go func() {
err := compressJSON(w, someObject)
w.CloseWithError(err)
}()
req, err := http.NewRequest("POST", "http://example.com/", r)
【讨论】: