首页 > 编程问答 >尝试解析文件中的多个 JSON 时字符索引不一致

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

时间:2024-07-26 04:14:58浏览次数:9  
标签:python json generator

我使用以下代码来解析 .json 文件中存储的流中以逗号分隔的 JSON 多行对象:

def stream_read_json(fn):
import json
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对象所在的字符时显示的字符数不同在文件上结束?

如何确保正确解析对象?

尝试在调试提示符处获取 f.seek(start_pos) 第二个 JSON 对象。


代码存在几个问题,导致在尝试解析文件中的多个 JSON 对象时出现“字符索引不一致”错误。让我们来分析一下问题,并提供解决方案:

问题分析

  1. f.read(e.pos) 不保证读取完整的 JSON 对象。 json.JSONDecodeError 中的 e.pos 指示发生错误的字符位置,但不一定是完整 JSON 对象的结束位置。这可能导致读取不完整的 JSON 字符串,从而在后续解析中出现错误。

  2. start_pos += e.pos 的逻辑错误。 即使 e.pos 正确指向了完整 JSON 对象的末尾, start_pos 的更新方式也会跳过对象之间的分隔符(例如逗号或换行符),导致后续解析从错误的位置开始。

解决方案

为了解决这些问题,我们需要确保每次读取完整的 JSON 对象,并正确更新 start_pos 。以下是一种改进后的实现:

import json

def stream_read_json(fn):
    with open(fn, 'r', encoding='utf-8') as f:
        buffer = ''
        for line in f:
            buffer += line
            while buffer:
                try:
                    obj, index = json.JSONDecoder().raw_decode(buffer)
                    yield obj
                    buffer = buffer[index:].lstrip()  # 去除前导空格
                except json.JSONDecodeError:
                    break

代码解释

  1. 按行读取文件: 使用 for line in f 逐行读取文件内容。

  2. 使用缓冲区: 将读取的行添加到 buffer 中,直到成功解析出一个完整的 JSON 对象。

  3. json.JSONDecoder().raw_decode(buffer) 使用 raw_decode 方法解析 JSON 对象。该方法返回解析后的对象和下一个 JSON 对象的起始索引。

  4. 更新缓冲区: 使用解析后的索引 index 更新 buffer ,确保下次解析从下一个 JSON 对象开始。

  5. 处理错误: 如果 json.JSONDecodeError 被引发,说明当前缓冲区中没有完整的 JSON 对象。此时,继续读取下一行并添加到缓冲区中。

示例

假设 data.json 文件包含以下内容:

{"name": "Alice", "age": 30}
{"name": "Bob", "age": 25}

使用改进后的 stream_read_json 函数:

for obj in stream_read_json('data.json'):
    print(obj)

输出:

{'name': 'Alice', 'age': 30}
{'name': 'Bob', 'age': 25}

总结

通过按行读取、使用缓冲区和 raw_decode 方法,我们可以更可靠地解析包含多个 JSON 对象的文件,避免“字符索引不一致”的错误。

标签:python,json,generator
From: 78795250

相关文章

  • 为什么在 Python 上使用正则表达式组功能会给出不同的输出
    importrestring1="aaabaa"zusuchen="aa"#1m_start=re.finditer(fr'(?=({zusuchen}))',string1)results=[(match.start(1),match.end(1)-1)formatchinm_start]forzinresults:print(z)print("Now#2:"......
  • 如何在python3中找到文件的长度?
    我的第一个.py:defcreate_file(file_name):list=["ab","cd","ef"]foriinlist:withopen(file_name,"a+")asinput_file:print("{}".format(i),file=input_file)我的第二个.py:fromfirstimport......
  • 哪种 python 日志记录风格是推荐的或标准的?
    我是Python新手。介于以下2个选项之间。对于python来说,推荐哪种风格或者更好?logging.info(f"Won'tsavemodelasscoreisbelow0,score:{score}")logging.info("Won'tsavemodelasscoreisbelow0,score%s",score)我个人更喜欢第二种方法。在Python......
  • python 协程 自定义互斥锁
    最近在用python的一款异步web框架sanic搭建web服务,遇到一个需要加特定锁的场景:同一用户并发处理订单时需要排队处理,但不同用户不需要排队。如果仅仅使用asyncwithasyncio.Lock()的话。会使所有请求都排队处理。1importasyncio2importdatetime34lock=asyncio.L......
  • Python 获取tiktok视频评论回复数据 api接口
    TIKTOKapi接口爬取tiktok视频评论回复数据详细采集页面如图https://www.tiktok.com/@dailymail/video/7329872821990182190?q=neural%20link&t=1706783508149请求APIhttp://api.xxxx.com/tt/video/info/comment/reply?video_id=7288909913185701125&comment_id=7294900......
  • Shopee虾皮api python获取虾皮购物平台的商品数据信息 数据采集
    虾皮购物(英语:Shopee)是一个电商平台,总公司设在新加坡,归属于SeaGroup(之前称之为Garena),该企业于2009年由李小冬(ForrestLi)创办。虾皮购物于2015年初次在新加坡推出,现阶段已拓展到马来西亚、泰国、印度尼西亚、越南和菲律宾。虾皮购物为全球华人地区的客户提供线上购物和销售......
  • GeoTools 读取 GeoPackage (`.gpkg`) 文件转为 GeoJSON
    要使用GeoTools读取GeoPackage(.gpkg)文件的第一个图层并将其转换为GeoJSON字符串,可以按照以下步骤进行:读取GeoPackage文件:使用GeoTools的DataStore类来访问GeoPackage文件。获取第一个图层:从DataStore中获取图层信息。将图层数据转换为GeoJSON:使用Featur......
  • python实现图像特征提取算法1
    python实现Marr-Hildreth算法、Canny边缘检测器算法1.Marr-Hildreth算法详解算法步骤公式Python实现详细解释优缺点2.Canny边缘检测器算法详解算法步骤公式Python实现详细解释优缺点1.Marr-Hildreth算法详解Marr-Hildreth算法是一个......
  • python实现盲反卷积算法
    python实现盲反卷积算法盲反卷积算法算法原理算法实现Python实现详细解释优缺点应用领域盲反卷积算法盲反卷积算法是一种图像复原技术,用于在没有先验知识或仅有有限信息的情况下,估计模糊图像的原始清晰图像和点扩散函数(PSF)。盲反卷积在摄影、医学成......
  • Python——异常捕获,传递及其抛出操作
    01.异常的概念1.程序在运行时,如果python解释器遇到一个错误,会停止程序的执行,并且提示一些错误信息,这就是异常。2.程序停止执行并且提示错误信息这个动作,我们通常称之为:抛出(raise)异常。 程序开发时,很难将所有的特殊情况都处理的面面俱到,通过异常捕获可以针对突发事件做......