如何从包含json数组的流中一次读取一个json对象,而不将整个数组加载到内存中?
为了减少内存使用和延迟,我希望在http响应中返回的json对象全部发送之前开始处理它们。 我正在尝试在我的web服务客户端上编写一个方法,该方法将查询一个web服务,返回一个通道,该通道将从web请求中提供结构,作为流的结束如何从包含json数组的流中一次读取一个json对象,而不将整个数组加载到内存中?,json,go,stream,Json,Go,Stream,为了减少内存使用和延迟,我希望在http响应中返回的json对象全部发送之前开始处理它们。 我正在尝试在我的web服务客户端上编写一个方法,该方法将查询一个web服务,返回一个通道,该通道将从web请求中提供结构,作为流的结束 func (c *Client) GetMyObj() (<-chan models.MyObj, <-chan error) { outChan := make(chan models.MyObj) errChan :=
func (c *Client) GetMyObj() (<-chan models.MyObj, <-chan error) {
outChan := make(chan models.MyObj)
errChan := make(chan error)
go func() {
resp, err := httpClient.Get(c.ServiceUrl, "text/plain;charset=UTF-8", nil)
if err != nil {
errChan <- err
return
}
if resp.Status != "200 OK" {
errChan <- fmt.Errorf("http error: %1", resp.Status)
return
}
dec := json.NewDecoder(resp.Body)
for dec.More() {
myO:= models.MyObj{}
err := dec.Decode(&MyO)
if err != nil {
errChan <- err
return
}
outChan <- dfe
}
}()
return outChan, errChan
}
中列出的示例正好说明了这一点
简而言之,您可以执行以下步骤:
dec.token()
读取令牌(并且可以选择将其预期为开放方括号)dec.Decode()
读取令牌,而dec.More()
(提示:
dec.Token
)我投票关闭这个问题,因为上面评论中链接的go文档提供了与此完全相同的示例代码。我查看了Token(),它看起来像是一直从流中读取,直到找到它读取的第一个括号或括号为止,并将所有读取部分添加到缓冲区中,如果是这种情况,它会将所有响应读取到内存中,这正是我试图避免的。我将深入研究解码器,看看我是否误解了。看起来它使用了一个缓冲窗口,而不是加载整个窗口,尽管从我的实验中我无法判断窗口大小是否每个周期增加512字节,即使是这样,这意味着它在解析1GB json文件时只会增加到略超过1MB。如果im服务多个请求,可能会出现问题,我喜欢将我的Go服务保持在spring boot应用程序配置文件的大小以下;)
[{"name":"Value"}
,{"name":"Value"}
,{"name":"Value"}]
dec := json.NewDecoder(jsonStream)
type Item struct{ Name string }
// Read the open bracket.
t, err := dec.Token()
if err != nil {
panic(err)
}
fmt.Printf("OK: %T: %v\n", t, t)
// While the array contains values.
for dec.More() {
// Decode an array value.
var item Item
err := dec.Decode(&item)
if err != nil {
panic(err)
}
fmt.Printf("OK: item=%#v\n", item)
}
// Read the closing bracket.
t, err = dec.Token()
if err != nil {
panic(err)
}
fmt.Printf("OK: %T: %v\n", t, t)
// OK: json.Delim: [
// OK: item=main.Item{Name:"Value1"}
// OK: item=main.Item{Name:"Value2"}
// OK: item=main.Item{Name:"Value3"}
// OK: json.Delim: ]