Как я могу читать объекты json по одному из потока, содержащего массив json, не загружая весь массив в память? - PullRequest
0 голосов
/ 10 октября 2018

Чтобы уменьшить использование памяти и уменьшить задержку, я хочу начать обработку json-объектов, возвращенных в HTTP-ответе, прежде чем они будут отправлены.Я пытаюсь написать метод на своем клиенте веб-службы, который будет запрашивать веб-службу, возвращая канал, который будет передавать структуры из веб-запроса по мере их выхода из потока.

    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 голосов
/ 10 октября 2018

Пример, приведенный в документации по методу json.Decoder.Decode(...) , показывает именно это.

Короче говоря, вы делаете следующие шаги:

  1. Чтение токенаиспользуя dec.Token() (и необязательно ожидайте, что это будет открытая квадратная скобка)
  2. Считайте токены, используя dec.Decode(), тогда как dec.More()
  3. При желании прочитайте заключительную заключительную квадратную скобку.

Например ( Go Playground ):

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: ]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...