从json流读取映射

从json流读取映射,json,go,Json,Go,我需要解析非常长的json文件(超过百万个条目)。我不想把它加载到内存中,然后一块一块地读。有一个关于项目数组的好例子。问题是我要处理地图。当我调用Decode时,我得到的不是在值的开头。 我弄不到该换的东西 常数数据=`{ “对象1”:{“名称”:“牛”,“位置”:“厨房”}, “object2”:{“name”:“table”,“location”:“office”} }` 类型ReadObject struct{ 名称字符串`json:“名称”` 位置字符串`json:“位置”` } f

我需要解析非常长的json文件(超过百万个条目)。我不想把它加载到内存中,然后一块一块地读。有一个关于项目数组的好例子。问题是我要处理地图。当我调用
Decode
时,我得到的
不是在值的开头。
我弄不到该换的东西


常数数据=`{
“对象1”:{“名称”:“牛”,“位置”:“厨房”},
“object2”:{“name”:“table”,“location”:“office”}
}`
类型ReadObject struct{
名称字符串`json:“名称”`
位置字符串`json:“位置”`
}
func ParseJSON(){
dec:=json.NewDecoder(strings.NewReader(数据))
tkn,err:=dec.Token()
如果错误!=零{
log.Fatalf(“未能读取开始标记:%v”,错误)
}
fmt.Printf(“开始标记:%v\n”,tkn)
对象:=make(映射[字符串]*ReadObject)
十二月更多(){
var nextSymbol字符串
如果错误:=dec.Decode(&nextSymbol);错误!=nil{
log.Fatalf(“未能分析下一个符号:%v”,错误)
}
下一个对象:=&ReadObject{}
如果错误:=dec.Decode(&nextObject);错误!=nil{
log.Fatalf(“未能分析下一个对象”)
}
对象[nextSymbol]=nextObject
}
tkn,err=dec.Token()
如果错误!=零{
log.Fatalf(“未能读取结束标记:%v”,错误)
}
fmt.Printf(“结束标记:%v\n”,tkn)
fmt.Printf(“对象:\n%v\n”,对象)
}

TL,DR:当您第一次调用
Token()
方法时,您会移动(JSON值)开头的偏移量,因此会出现错误

您正在使用此结构():

注意标记状态字段。此值可以是()中的一个:

让我们回到你的代码。您正在调用
Token()
方法。此方法获取第一个JSON有效令牌
{
,并将令牌状态从tokenObjectValue更改为tokenObjectStart()。现在您处于“对象”状态

如果此时尝试调用
Decode()
,则会出现错误(不是在值的开头)。这是因为调用
Decode()
允许的tokenState状态是tokenTopValue、tokenarraryStart、tokenarraryValue、tokenObjectValue,即“完整”值,而不是其一部分()

为了避免这种情况,您可以根本不调用
Token()
,而是执行以下操作:

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

objects := make(map[string]*ReadObject)
if err := dec.Decode(&objects); err != nil {
    log.Fatalf("failed to parse next symbol: %v", err)
}

fmt.Printf("OBJECTS: \n%v\n", objects)

或者,如果您想逐块读取,您可以继续调用
Token()
,直到达到“full”值。然后对该值调用
Decode()
(我想应该可以了)。

在第一次调用
dec.Token()
消耗初始
后,您必须:

  • 使用
    dec.Token()
    提取下一个密钥
  • 提取密钥后,可以调用
    dec.Decode(&nextObject)
    对条目进行解码
示例代码:

    for dec.More() {
        key, err := dec.Token()
        if err != nil {
            // handle error
        }

        var val interface{}
        err = dec.Decode(&val)
        if err != nil {
            // handle error
        }

        fmt.Printf("  %s : %v\n", key, val)
    }

你可以一块一块地加载文件,手动查找每个元素,提取并解析它。你想让我演示一下吗?如果你已经有了一个很好的示例。如果没有–不用担心
dec := json.NewDecoder(strings.NewReader(dataMapFromJson))

objects := make(map[string]*ReadObject)
if err := dec.Decode(&objects); err != nil {
    log.Fatalf("failed to parse next symbol: %v", err)
}

fmt.Printf("OBJECTS: \n%v\n", objects)
    for dec.More() {
        key, err := dec.Token()
        if err != nil {
            // handle error
        }

        var val interface{}
        err = dec.Decode(&val)
        if err != nil {
            // handle error
        }

        fmt.Printf("  %s : %v\n", key, val)
    }