首頁 >後端開發 >Golang >如何在不將整個負載載入到記憶體的情況下高效解碼 JSON 流?

如何在不將整個負載載入到記憶體的情況下高效解碼 JSON 流?

Barbara Streisand
Barbara Streisand原創
2024-12-25 18:44:14943瀏覽

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 流中的下一個標記,使我們能夠增量處理資料。

On-the- Fly 令牌處理

我們建立一個「狀態機」來追蹤我們在 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中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn