本文将讲解一个实例,你的程序从不可靠的源中使用JSON,而JSON包含一个对象数组,这些对象具有开始标记[
但数组中的项目数非常大,并且JSON的结尾可能被破坏。
从不完整的JSON数组中提取数据
Golang 版本
1.12.1
前沿
本文将讲解一个实例,你的程序从不可靠的源中使用JSON,而JSON包含一个对象数组,这些对象具有开始标记[
但数组中的项目数非常大,并且JSON的结尾可能被破坏。
实现
package main
import (
"encoding/json"
"fmt"
"strings"
)
const js = `
[
{
"name":"Axel",
"lastname":"Fooley"
},
{
"name":"Tim",
"lastname":"Burton"
},
{
"name":"Tim",
"lastname":"Burton"
`
type User struct {
Name string `json:"name"`
LastName string `json:"lastname"`
}
func main() {
userSlice := make([]User, 0)
r := strings.NewReader(js)
dec := json.NewDecoder(r)
for {
tok, err := dec.Token()
if err != nil {
break
}
if tok == nil {
break
}
switch tp := tok.(type) {
case json.Delim:
str := tp.String()
if str == "[" || str == "{" {
for dec.More() {
u := User{}
err := dec.Decode(&u)
if err == nil {
userSlice = append(userSlice, u)
} else {
break
}
}
}
}
}
fmt.Println(userSlice)
}
$go run main.go
[{Axel Fooley} {Tim Burton}]
原理
除了Unmarshall
函数,json
包还包含Decoder
API。 使用NewDecoder
,可以创建Decoder
。 通过在解码器上调用Token
方法,读取底层Reader
并返回Token
接口。 这可能包含多个值。
其中一个是Delim
类型,它是一个包含{
,[
,]
,}
字符之一的rune。 基于此,检测到JSON数组的开头。 利用解码器上的More
方法,可以检测到更多要解码的对象。