Heim >Backend-Entwicklung >Golang >Wie kann man große Streaming-JSON-Dateien in Go effizient dekodieren?

Wie kann man große Streaming-JSON-Dateien in Go effizient dekodieren?

Mary-Kate Olsen
Mary-Kate OlsenOriginal
2025-01-02 20:03:40346Durchsuche

How to Efficiently Decode Large Streaming JSON in Go?

So dekodieren Sie Streaming-JSON in Go

Wenn Sie mit großen JSON-Antworten arbeiten, ist es nicht ideal, die gesamte Antwort vor der Dekodierung in den Speicher zu laden. Die Verwendung der Funktion ioutil.ReadAll kann bei der Verarbeitung großer JSON-Nutzlasten zu Speicherproblemen führen. In diesem Artikel erfahren Sie, wie Sie JSON-Daten während des Streams im Handumdrehen dekodieren und so Speicherverbrauchsprobleme vermeiden können.

JSON-Streaming mit json.Decoder

Der json.Decoder in der Go-Standardbibliothek bietet die Möglichkeit, JSON-Streams inkrementell zu analysieren. Dies wird durch die Decoder.Token()-Methode erreicht.

Die Decoder.Token()-Methode gibt das nächste Token im JSON-Stream zurück, ohne es zu verbrauchen. Dies ermöglicht ein selektives Parsen von JSON-Daten und eine ereignisgesteuerte Verarbeitung.

Umgang mit JSON-Strukturen

Für das ereignisgesteuerte Parsen ist eine Zustandsmaschine erforderlich, um die aktuelle Position innerhalb der JSON-Struktur zu verfolgen. Wir können diese Zustandsmaschine verwenden, um verschiedene Teile der JSON-Daten so zu verarbeiten, wie sie im Stream erscheinen.

Nehmen wir zum Beispiel an, wir erhalten eine JSON-Antwort mit dem folgenden Format:

{
    "property1": "value1",
    "property2": "value2",
    "array": [
        { "item1": "value3" },
        { "item2": "value4" }
    ]
}

Wir können eine Funktion schreiben, die diesen JSON-Stream inkrementell analysiert und das Array-Element separat verarbeitet:

func processJSONStream(stream io.Reader) {
    decoder := json.NewDecoder(stream)

    state := "start"
    for decoder.More() {
        token, err := decoder.Token()
        if err != nil {
            log.Fatal(err)
        }

        switch state {
        case "start":
            if delim, ok := token.(json.Delim); ok && delim == '{' {
                state = "object"
            } else {
                log.Fatal("Expected object")
            }
        case "object":
            switch t := token.(type) {
            case json.Delim:
                if t == '}' {
                    // End of object
                    state = "end"
                } else if t == ',' {
                    // Next property
                    continue
                } else if t == '[' {
                    // Array found
                    state = "array"
                }

                if t == ':' {
                    // Property value expected
                    state = "prop_value"
                }
            case string:
                // Property name
                fmt.Printf("Property '%s'\n", t)
            default:
                // Property value
                fmt.Printf("Value: %v\n", t)
            }
        case "array":
            if delim, ok := token.(json.Delim); ok && delim == ']' {
                // End of array
                state = "object"
            } else if token == json.Delim('{') {
                // Array item object
                fmt.Printf("Item:\n")
                state = "item"
            }
        case "item":
            switch t := token.(type) {
            case json.Delim:
                if t == '}' {
                    // End of item object
                    fmt.Printf("\n")
                    state = "array"
                } else if t == ',' {
                    // Next item property
                    fmt.Printf(",\n")
                    continue
                }
            case string:
                // Item property name
                fmt.Printf("\t'%s'", t)
            default:
                // Item property value
                fmt.Printf(": %v", t)
            }
        case "prop_value":
            // Decode the property value
            var value interface{}
            if err := decoder.Decode(&value); err != nil {
                log.Fatal(err)
            }
            fmt.Printf("Value: %v\n", value)
            state = "object"
        }
    }
}

Bei Aufruf mit der JSON-Antwort wird diese Funktion ausgeführt Geben Sie die Eigenschaftsnamen und -werte sowie die einzelnen Elemente innerhalb des Arrays aus.

Fazit

Die Verwendung von json.Decoder und Decoder.Token() in der ereignisgesteuerten Verarbeitung ermöglicht uns das Parsen große JSON-Antworten inkrementell, um Probleme mit dem Speicherverbrauch zu vermeiden und eine effiziente Verarbeitung der Daten beim Einströmen zu ermöglichen.

Das obige ist der detaillierte Inhalt vonWie kann man große Streaming-JSON-Dateien in Go effizient dekodieren?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn