Maison >développement back-end >Golang >Comment décoder efficacement les flux JSON sans charger l'intégralité de la charge utile en mémoire ?

Comment décoder efficacement les flux JSON sans charger l'intégralité de la charge utile en mémoire ?

Barbara Streisand
Barbara Streisandoriginal
2024-12-25 18:44:14941parcourir

How to Efficiently Decode JSON Streams without Loading the Entire Payload into Memory?

Décoder les flux JSON sans lire l'intégralité de la charge utile

Dans ce scénario, nous rencontrons la nécessité de décoder les données JSON reçues via le streaming HTTP sans charger le la réponse entière en mémoire. L'objectif est de traiter des éléments JSON individuels (représentés comme des « gros objets » dans un tableau) et de les envoyer vers une file d'attente de messages au fur et à mesure de leur réception.

Analyse JSON basée sur les événements

Pour y parvenir, nous utilisons le json.Decoder et ses méthodes Decode() et Token(). Decode() peut être utilisé pour désassembler une seule valeur, tandis que Token() nous permet d'analyser uniquement le jeton suivant dans le flux JSON, nous permettant ainsi de traiter les données de manière incrémentielle.

Sur le- Traitement des jetons Fly

Nous établissons une « machine à états » pour suivre notre position au sein de la structure JSON. En analysant chaque jeton, nous naviguons dans la hiérarchie des objets, en identifiant le tableau « éléments » et ses grands éléments d'objet.

Implémentation du code

package main

import (
    "bufio"
    "encoding/json"
    "fmt"
    "io"
    "log"
    "os"
)

// Helper error handler
func he(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

// Large object struct
type LargeObject struct {
    Id   string `json:"id"`
    Data string `json:"data"`
}

func main() {
    // JSON input for demonstration
    in := `{"somefield": "value", "otherfield": "othervalue", "items": [ {"id": "1", "data": "data1"}, {"id": "2", "data": "data2"}, {"id": "3", "data": "data3"}, {"id": "4", "data": "data4"}]}`

    dec := json.NewDecoder(strings.NewReader(in))

    // Expect an object
    t, err := dec.Token()
    he(err)
    if delim, ok := t.(json.Delim); !ok || delim != '{' {
        log.Fatal("Expected object")
    }

    // Read props
    for dec.More() {
        t, err = dec.Token()
        he(err)
        prop := t.(string)
        if t != "items" {
            var v interface{}
            he(dec.Decode(&v))
            fmt.Printf("Property '%s' = %v\n", prop, v)
            continue
        }

        // It's the "items". Expect an array
        t, err = dec.Token()
        he(err)
        if delim, ok := t.(json.Delim); !ok || delim != '[' {
            log.Fatal("Expected array")
        }
        // Read items (large objects)
        for dec.More() {
            // Read next item (large object)
            lo := LargeObject{}
            he(dec.Decode(&lo))
            fmt.Printf("Item: %+v\n", lo)
        }
        // Array closing delim
        t, err = dec.Token()
        he(err)
        if delim, ok := t.(json.Delim); !ok || delim != ']' {
            log.Fatal("Expected array closing")
        }
    }

    // Object closing delim
    t, err = dec.Token()
    he(err)
    if delim, ok := t.(json.Delim); !ok || delim != '}' {
        log.Fatal("Expected object closing")
    }
}

Exemple de sortie

Property 'somefield' = value
Property 'otherfield' = othervalue
Item: {Id:1 Data:data1}
Item: {Id:2 Data:data2}
Item: {Id:3 Data:data3}
Item: {Id:4 Data:data4}

En utilisant cette approche d'analyse basée sur les événements, nous pouvons traiter efficacement les grandes réponses JSON progressivement, en évitant une consommation excessive de mémoire.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn