尝试解析文件中的多个 JSON 时字符索引不一致

问题描述 投票:0回答:2

我使用以下代码从存储在 .json 文件中的网络抓取字符串中解析以逗号分隔的 JSON 多行对象:

import json

def stream_read_json(fn):
    start_pos = 0
    with open(fn, 'r', encoding='utf-8') as f:
        while True:
            try:
                obj = json.load(f)
                yield obj
                return
            except json.JSONDecodeError as e:
                f.seek(start_pos)
                json_str = f.read(e.pos)
                obj = json.loads(json_str, encoding = 'utf-8')
                start_pos += e.pos
                yield obj

第一个对象解析正确;接下来的不是。 在测试

f.seek(start_pos)
的随机值时,我发现与
except json.JSONDecodeError as e:
找到的索引不一致。为什么此索引与我在 IDE 上选择文本直到文件中 JSON 对象结束的字符时显示的字符数不同?

如何确保对象被正确解析?

我尝试在调试提示符处获取第二个 JSON 对象的

f.seek(start_pos)
,但它与错误抛出的
e.pos
有很大不同。

JSON 示例如下:

{
  "user": {
    "id": 1,
    "profile": {
      "name": "Alice",
      "age": 30
    }
  },
  "product": {
    "sku": "A1234",
    "details": {
      "name": "Laptop",
      "price": 999.99
    }
  }
},
{
  "user": {
    "id": 2,
    "profile": {
      "name": "Bob",
      "age": 22
    }
  },
  "product": {
    "sku": "A123w",
    "details": {
      "name": "Laptop",
      "price": 9.99
    }
  }
}
python json generator
2个回答
0
投票

这绝对不是正确的方法,应该如何完成,但我会针对您的特定情况建议一种解决方法。

问题是你的“json”并不是真正的json,因为缺少括号

[]
和很多重复的键。但作为解决方法,您可以执行以下操作:

import json

with open("test.json", "r") as file:
    str_data: str = file.read()
    dict_data: dict = json.loads(f"[{str_data}]")

0
投票

是的,可以这样做,但我不推荐这样做。

您的问题是:

  1. 您已将
    encoding=
    添加到
    json.loads()
  2. 您忽略了分隔 json 对象的逗号

我测试过这段代码:

def stream_read_json(fn):
    start_pos = 0
    with open(fn, 'r', encoding='utf-8') as f:
        while True:
            try:
                obj = json.load(f)
                yield obj
                return
            except json.JSONDecodeError as e:
                f.seek(start_pos)
                json_str = f.read(e.pos)
                obj = json.loads(json_str)
                yield obj
                f.read(1)
                start_pos += e.pos + 1
© www.soinside.com 2019 - 2024. All rights reserved.