在不读取整个有效负载的情况下解码 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中文网其他相关文章!