2015-08-03 17 views
10

Ho un enorme array JSON memorizzato in un file ("file.json") Ho bisogno di scorrere l'array e fare qualche operazione su ciascun elemento.Stream grande JSON

err = json.Unmarshal(dat, &all_data) 

Provoca un esaurimento della memoria - Sto indovinando perché carica tutto in memoria prima.

C'è un modo per trasmettere l'elemento JSON per elemento?

+2

il lib std non prevede nulla di simile ancora, ma I'ts prossimamente: vedi https://go-review.googlesource.com/#/c/9073/, si potrebbe dare un'occhiata a l'implementazione per avere un'idea di come analizzare personalmente il tuo speciale june –

+0

@AdamVincze: in arrivo, come in go1.5, che è dovuto in qualsiasi momento ora;) (per i documenti di sviluppo attuali, puoi sempre usare "tip.golang.org" "http://tip.golang.org/pkg/encoding/json/) – JimB

+1

Questo è stato veloce - https://github.com/golang/go/issues/12001 – Sridhar

risposta

2

Così, come commentatori hanno suggerito, è possibile utilizzare l'API di streaming di "codifica/json" per la lettura di una corda alla volta:

r := ... // get some io.Reader (e.g. open the big array file) 
d := json.NewDecoder(r) 
// read "[" 
d.Token() 
// read strings one by one 
for d.More() { 
    s, _ := d.Token() 
    // do something with s which is the newly read string 
    fmt.Printf("read %q\n", s) 
} 
// (optionally) read "]" 
d.Token() 

Si noti che per semplicità ho lasciato la gestione errori fuori che ha bisogno da implementare.

8

C'è un esempio di questo tipo di cose qui: https://golang.org/pkg/encoding/json/#example_Decoder_Decode_stream.

package main 

import (
    "encoding/json" 
    "fmt" 
    "log" 
    "strings" 
) 

func main() { 
    const jsonStream = ` 
       [ 
        {"Name": "Ed", "Text": "Knock knock."}, 
        {"Name": "Sam", "Text": "Who's there?"}, 
        {"Name": "Ed", "Text": "Go fmt."}, 
        {"Name": "Sam", "Text": "Go fmt who?"}, 
        {"Name": "Ed", "Text": "Go fmt yourself!"} 
       ] 
      ` 
    type Message struct { 
     Name, Text string 
    } 
    dec := json.NewDecoder(strings.NewReader(jsonStream)) 

    // read open bracket 
    t, err := dec.Token() 
    if err != nil { 
     log.Fatal(err) 
    } 
    fmt.Printf("%T: %v\n", t, t) 

    // while the array contains values 
    for dec.More() { 
     var m Message 
     // decode an array value (Message) 
     err := dec.Decode(&m) 
     if err != nil { 
      log.Fatal(err) 
     } 

     fmt.Printf("%v: %v\n", m.Name, m.Text) 
    } 

    // read closing bracket 
    t, err = dec.Token() 
    if err != nil { 
     log.Fatal(err) 
    } 
    fmt.Printf("%T: %v\n", t, t) 

}