我如何一次从包含json数组的流中读取一个json对象,而不将整个数组加载到内存中?

时间:2018-10-10 18:53:54

标签: json go stream

为减少内存使用量并减少延迟,我想开始处理http响应中返回的json对象,然后将其全部发送出去。 我正在尝试在我的Web服务客户端上编写一个方法,该方法将查询Web服务并返回一个通道,该通道将在退出流时从Web请求中馈送结构。

    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
    }

不幸的是,当它读取前面的方括号时会产生异常。json文档看起来类似于以下内容,但是数组中有更多的对象,并且该对象具有更多的属性,但是您有了主意:

    [{"name":"Value"}
    ,{"name":"Value"}
    ,{"name":"Value"}]

1 个答案:

答案 0 :(得分:2)

json.Decoder.Decode(...) method documentation中列出的示例完全显示了这一点。

简而言之,请执行以下步骤:

  1. 使用public async Task<ContentResult> OnGetActivityLog([FromQuery] string PartitionKey, string RowKey, string ComputerName) { Activities = await _azureTableConnection.GetActivitiesAsync(PartitionKey, RowKey, ComputerName); return Content(JsonConvert.SerializeObject(new { Activities })); } 读取令牌(并且可以选择将其用作方括号)
  2. dec.Token()时使用dec.Decode()读取令牌
  3. (可选)阅读最后一个方括号。

例如(Go Playground):

dec.More()