對json.Decoder
可能解碼JSON流。我們可以讀取(解組)單個值而不消耗和解組整個流。這很酷,但是您的輸入是一個「單個」JSON對象,而不是一系列JSON對象,這意味着要調用Decoder.Decode()
會試圖解組所有項目(大對象)的完整JSON對象。
我們想要的是部分地對單個JSON對象進行即時處理。爲此,我們可以使用Decoder.Token()
,它僅解析(前進)JSON輸入流中的下一個後續標記並將其返回。這被稱爲事件驅動的解析。
當然,我們必須「處理」(解釋並採取行動)令牌並構建一個「狀態機」,以跟蹤我們處於我們正在處理的JSON結構中的位置。
這是一個解決您的問題的實現。
我們將使用以下JSON輸入:
{
"somefield": "value",
"otherfield": "othervalue",
"items": [
{ "id": "1", "data": "data1" },
{ "id": "2", "data": "data2" },
{ "id": "3", "data": "data3" },
{ "id": "4", "data": "data4" }
]
}
還要讀items
的「大對象」的這種類型的建模:
type LargeObject struct {
Id string `json:"id"`
Data string `json:"data"`
}
我們還將分析和解釋在其他領域JSON對象,但我們只會記錄/打印它們。
爲了簡潔和便於錯誤處理,我們將使用這個助手的錯誤處理功能:
he := func(err error) {
if err != nil {
log.Fatal(err)
}
}
現在讓我們來看看一些行動。在下面的示例中,爲了簡潔起見,並在Go Playground上進行了演示,我們將從string
的值中讀取值。要從實際HTTP響應正文閱讀,我們只有改變單一的線,這是我們如何創造json.Decoder
:
dec := json.NewDecoder(res.Body)
所以演示:
dec := json.NewDecoder(strings.NewReader(jsonStream))
// We 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))
log.Printf("Property '%s' = %v", prop, v)
continue
}
// It's the "items". We expect it to be 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")
}
這將產生以下輸出:
2009/11/10 23:00:00 Property 'somefield' = value
2009/11/10 23:00:00 Property 'otherfield' = othervalue
Item: {Id:1 Data:data1}
Item: {Id:2 Data:data2}
Item: {Id:3 Data:data3}
Item: {Id:4 Data:data4}
嘗試使用Go Playground的完整工作示例。
[請參閱文檔中的示例](https://godoc.org/encoding/json#example-Decoder-Decode-Stream)。 –