2015-08-03 3 views
10

Ich habe eine massive JSON-Array in einer Datei gespeichert ("file.json") Ich muss durchlaufen das Array und einige Operationen auf jedem Element.Stream groß JSON

Verursacht einen zu großen Speicher - ich schätze, weil es zuerst alles in den Speicher lädt.

Gibt es eine Möglichkeit, das JSON-Element elementweise zu streamen?

+2

die std lib bietet keine so etwas noch nicht, aber bald i'ts kommen: siehe https://go-review.googlesource.com/#/c/9073/, könnten Sie einen Blick auf, die Implementierung, um eine Idee zu bekommen, wie Sie Ihre speziellen JSON selbst analysieren –

+0

@AdamVincze: kommt bald, wie in go1.5, die zu jeder Zeit fällig ist;) (für die aktuelle Entwicklung Dokumente können Sie immer "tip.golang.org "http://tip.golang.org/pkg/encoding/json/) – JimB

+1

Das war schnell - https://github.com/golang/go/issues/12001 – Sridhar

Antwort

2

So, wie commen vorgeschlagen, könnten Sie die Streaming-API von „encoding/json“ zu einer Zeit zum Lesen einer Zeichenfolge verwenden:

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() 

Beachten Sie, dass der Einfachheit halber ich Fehler habe weggelassen Umgang welche Bedürfnisse Implementiert sein.

8

Es gibt ein Beispiel für diese Art von Sache hier: 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) 

} 
Verwandte Themen