I have a JSON object of type []byte
that I created from a struct using json.Marshal
. I want to GZip the JSON before posting it to my endpoint. The following does not work:
gz := gzip.NewWriter(myJSON)
because []byte
does not implement io.Writer
.
Is there some very simple way I can do this once I already have my JSON created?
Compress to a buffer and post that buffer.
var buf bytes.Buffer
gz := gzip.NewWriter(&buf)
gz.Write(myJSON)
gz.Close()
Because a *bytes.Buffer
statisifies the io.Reader
interface, you can use the buffer directly when creating the request.
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")
The best option is to stream your JSON marshaling to your gzip writer:
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()
}
This has the advantage of not buffering your json in memory temporarily, so it will be faster and use less RAM.
If you need this as an io.Reader
, such as for the body of an HTTP request, you can use a pipe to do the conversion:
r, w := io.Pipe()
go func() {
err := compressJSON(w, someObject)
w.CloseWithError(err)
}()
req, err := http.NewRequest("POST", "http://example.com/", r)