简体   繁体   English

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

[英]How to encode a struct back to a bytes buffer

I am making a API request and the response I get back is a bytes.Buffer. 我正在发出一个API请求,我得到的响应是一个bytes.Buffer。 I then json decode that into my struct: 然后,我将json解码为我的结构:

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

result := MyStruct{}
err = json.NewDecoder(response).Decode(&result)

I know want to take my struct, result, and gzip it. 我知道要接受我的结构,结果并gzip。

Should I be using a json decoder to get the value back? 我应该使用json解码器取回值吗?

I want to then take that decoded json so I can then gzip it eventually. 然后,我想使用该解码的json,以便最终将其gzip压缩。

Also, I am confused between a byte array, bytebuffer and then these readers. 另外,我在字节数组,字节缓冲区和这些读取器之间感到困惑。 Is this hierarchy like java? 这个层次结构像Java吗?

If you want to store your struct as json, the simplest way is usually to use json.Marshal() , as in: 如果要将结构存储为json,最简单的方法通常是使用json.Marshal() ,如下所示:

b, err := json.Marshal(&myStruct)

b will in this case be a byte slice ([]byte). 在这种情况下,b将是字节片([] byte)。 This can later be gzipped using the gzip package. 以后可以使用gzip包将其压缩。 For instance, to gzip the bytes to a file, you could use: 例如,要将字节gzip压缩到文件中,可以使用:

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

w := gzip.NewWriter(f)
w.Write(b)
w.Close()

If you want to, you can bypass creating the byte slice by using json.Encoder.Encode() directly instead. 如果愿意,可以直接使用json.Encoder.Encode()绕过创建字节片。

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

w := gzip.NewWriter(f)
json.NewEncoder(w).Encode(&myStruct)
w.Close()

Depending on where you want to store or send the gzipped json, you can replace the parameter f used in gzip.NewWriter(f) to be any object that implements io.Writer . 根据要存储或发送gzip json的位置,可以将gzip.NewWriter(f)使用的参数f替换为实现io.Writer任何对象。 For instance, you can send the gzipped response using http.ResponseWriter directly in a handler: 例如,您可以直接在处理程序中使用http.ResponseWriter发送压缩后的响应:

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

I am a bit confused by your question but maybe this helps a bit: 您的问题让我有些困惑,但这也许会有所帮助:

Assuming you would use the standard http.Client your HTTP call would be done via Client.Do which returns an *http.Response . 假设您将使用标准的http.Client则将通过Client.Do完成HTTP调用,该Client.Do返回*http.Response

You can read the response body from the Body field which is of type io.ReadCloser . 您可以从读取响应体Body场这类型的io.ReadCloser This is actually just an interface that combines the io.Reader and io.Closer interface. 实际上,这只是一个结合了io.Readerio.Closer接口的接口。 If you know the response is json you can now create a json.Decoder using json.NewDecoder which accepts any io.Reader . 如果你知道响应是json ,你现在可以创建一个json.Decoder使用json.NewDecoder它接受任何io.Reader

Its important to keep in mind that all types implicitly implement io.Reader by having the following function defined on them: 重要的是要记住,所有类型io.Reader通过在其上定义以下功能来隐式实现io.Reader

Read(p []byte) (n int, err error)

Just as the *http.Response Body field is an io.Reader any bytes.Buffer implements io.Reader because it implements the Buffer.Read function. 就像*http.Response Body字段是io.Reader任何bytes.Buffer实现io.Reader因为它实现了Buffer.Read函数。

In contrast a []byte (byte array) is a scalar type that does not implement any functions on its own. 相反, []byte (字节数组)是一种标量类型,它自己无法实现任何功能。 Therefore []byte does not implement io.Reader so you can not just pass this into json.NewDecoder . 因此[]byte没有实现io.Reader所以您不能仅将其传递给json.NewDecoder If you want to decode JSON from a byte array/slice you should probably just use json.Unmarshal or create a bytes.Buffer from your []byte using bytes.NewBuffer and then again pass that to the json.Decoder . 如果您想从字节数组/切片中解码JSON,则可能应该使用json.Unmarshal或使用bytes.Buffer[]byte创建一个bytes.NewBuffer ,然后再次将其传递给json.Decoder

The same concepts apply for encoding JSON back but this time instead of an io.Reader you need an io.Writer and a json.Encoder . 同样的概念适用于编码JSON回来,但这个时候,而不是一个io.Reader你需要一个io.Writerjson.Encoder

io.Reader and io.Writer are interfaces specifying object behaviour regardless of it implementation. io.Readerio.Writer是指定对象行为的接口,无论其实现如何。 bytes.Buffer is data structure implementing both io.Reader and io.Writer . bytes.Buffer是同时实现io.Readerio.Writer数据结构。 array is just core language data structure similar with others languages have. 数组只是核心语言数据结构,与其他语言类似。 Most interfaces advantage is you can operate with them uniformly despite underlying implementations. 大多数接口的优点是,尽管有底层实现,您也可以统一使用它们。 For example io library has func TeeReader(r Reader, w Writer) Reader which returns a Reader that writes to w what it reads from r. 例如,io库具有func TeeReader(r Reader, w Writer) Reader ,它返回一个读取器,该读取器向w写入从r读取的内容。 You can use it to gzip response as you read and decode it. 您可以在读取和解码它时使用它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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM