>백엔드 개발 >Golang >전체 페이로드를 메모리에 로드하지 않고 JSON 스트림을 효율적으로 디코딩하는 방법은 무엇입니까?

전체 페이로드를 메모리에 로드하지 않고 JSON 스트림을 효율적으로 디코딩하는 방법은 무엇입니까?

Barbara Streisand
Barbara Streisand원래의
2024-12-25 18:44:14941검색

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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.