ホームページ > バックエンド開発 > Golang > ペイロード全体をメモリにロードせずに JSON ストリームを効率的にデコードするにはどうすればよいですか?

ペイロード全体をメモリにロードせずに JSON ストリームを効率的にデコードするにはどうすればよいですか?

Barbara Streisand
リリース: 2024-12-25 18:44:14
オリジナル
939 人が閲覧しました

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

ペイロード全体を読み取らずに JSON ストリームをデコードする

このシナリオでは、HTTP ストリーミング経由で受信した JSON データを、データをロードせずにデコードする必要があります。反応全体が記憶に残ります。目的は、個々の JSON 項目 (配列内の「ラージ オブジェクト」として表される) を処理し、受信したときにメッセージ キューにディスパッチすることです。

イベント駆動型 JSON 解析

これを実現するために、json.Decoder とその Decode() および Token() メソッドを使用します。 Decode() を使用すると単一の値をアンマーシャリングできますが、Token() を使用すると JSON ストリーム内の次のトークンのみを解析できるため、データを段階的に処理できます。

フライ トークンの処理

JSON 構造内での位置を追跡するために「ステート マシン」を確立します。各トークンを分析することで、オブジェクト階層をナビゲートし、「items」配列とその大きなオブジェクト要素を特定します。

コード実装

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")
    }
}
ログイン後にコピー

サンプル出力

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}
ログイン後にコピー

これを使用するとイベント駆動型の解析アプローチにより、大規模な JSON 応答を効果的に段階的に処理し、過度のメモリ消費を回避できます。

以上がペイロード全体をメモリにロードせずに JSON ストリームを効率的にデコードするにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート