有效地确定JSON标签

时间:2018-10-03 06:10:56

标签: json go

我有一堆JSON文件,每个文件包含大量复杂数据。 JSON文件类似于:

ids.json

{
    "ids": [1,2,3]
}

names.json:

{
    "names": ["Tyrion","Jaime","Cersei"]
}

,依此类推。 (实际上,数组元素是具有十个字段的复杂结构对象)

我想提取 just 标签,该标签指定其包含的数组类型。目前,我正在使用encoding/json将整个文件解组为map[string]interface{}并遍历地图,但这是一项昂贵的操作。

是否有一种更快的方式来做到这一点,最好不要拆散整个数据?

2 个答案:

答案 0 :(得分:1)

您可以在打开花括号后立即使阅读器偏移,然后使用json.Decoder仅解码来自阅读器的第一个令牌

类似的事情

sr := strings.NewReader(`{
    "ids": [1,2,3]
}`)

for {
    b, err := sr.ReadByte()
    if err != nil {
        fmt.Println(err)
        return
    }
    if b == '{' {
        break
    }
}

d := json.NewDecoder(sr)

var key string
err := d.Decode(&key)
if err != nil {
    fmt.Println(err)
    return
}

fmt.Println(key)

https://play.golang.org/p/xJJEqj0tFk9

另外,您可以将io.Reader中获得的openbufio.Reader包装,以避免多次单字节写操作

此解决方案假定内容是有效的JSON对象。并不是说您还是可以避免这种情况。

答案 1 :(得分:1)

我有个玩法,Decoder.Token()一次读取一个令牌(请参阅此example,第87行),并且可以提取数组标签:

const jsonStream = `{
    "ids": [1,2,3]
}`

dec := json.NewDecoder(strings.NewReader(jsonStream))

t, err := dec.Token()
if err != nil {
    log.Fatal(err)
}

fmt.Printf("First token: %v\n", t)

t, err = dec.Token()
if err != nil {
    log.Fatal(err)
}

fmt.Printf("Second token (array label): %v\n", t)