Для потоковой передачи массива объектов JSON необходимо декодировать вложенные объекты вместо объекта root. Для этого вам нужно прочитать данные с помощью токенов ( check Token
method ). Согласно документации:
Token возвращает следующий JSON токен во входном потоке. В конце входного потока Token возвращает nil
, io.EOF
.
Token гарантирует, что возвращаемые им разделители [
]
{
}
правильно вложены и сопоставлены: если Токен обнаружит неожиданный разделитель во входных данных, он вернет ошибку.
Входной поток состоит из базовых c JSON значений - bool, string, number и null - вместе с разделителями [
]
{
}
типа Delim для обозначения начала и конца массивов и объектов. Запятые и двоеточия исключаются.
Это означает, что вы можете декодировать документ по частям. Найдите официальный пример, как это сделать здесь
Я опубликую фрагмент кода, который покажет, как вы можете объединить json stream techni c с записью результата в CSV:
package main
import (
"encoding/csv"
"encoding/json"
"log"
"os"
"strings"
)
type RecordStruct struct {
Name string `json:"name"`
Info string `json:"info"`
// ... any field you want
}
func (rs *RecordStruct) CSVRecord() []string {
// Here we form data for CSV writer
return []string{rs.Name, rs.Info}
}
const jsonData =
`[
{ "name": "Full Name", "info": "..."},
{ "name": "Full Name", "info": "..."},
{ "name": "Full Name", "info": "..."},
{ "name": "Full Name", "info": "..."},
{ "name": "Full Name", "info": "..."}
]`
func main() {
// Create file for storing our result
file, err := os.Create("result.csv")
if err != nil {
log.Fatalln(err)
}
defer file.Close()
// Create CSV writer using standard "encoding/csv" package
var w = csv.NewWriter(file)
// Put your reader here. In this case I use strings.Reader
// If you are getting data through http it will be resp.Body
var jsonReader = strings.NewReader(jsonData)
// Create JSON decoder using "encoding/json" package
decoder := json.NewDecoder(jsonReader)
// Token returns the next JSON token in the input stream.
// At the end of the input stream, Token returns nil, io.EOF.
// In this case our first token is '[', i.e. array start
_, err = decoder.Token()
if err != nil {
log.Fatalln(err)
}
// More reports whether there is another element in the
// current array or object being parsed.
for decoder.More() {
var record RecordStruct
// Decode only the one item from our array
if err := decoder.Decode(&record); err != nil {
log.Fatalln(err)
}
// Convert and put out record to the csv file
if err := writeToCSV(w, record.CSVRecord()); err != nil {
log.Fatalln(err)
}
}
// Our last token is ']', i.e. array end
_, err = decoder.Token()
if err != nil {
log.Fatalln(err)
}
}
func writeToCSV(w *csv.Writer, record []string) error {
if err := w.Write(record); err != nil {
return err
}
w.Flush()
return nil
}
Вы также можете использовать сторонние пакеты, такие как github.com / bcicen / jstream