新闻中心

处理非标准多对象JSON响应:Python解析策略与实践

2025-12-14
浏览次数:
返回列表

处理非标准多对象JSON响应:Python解析策略与实践

本教程旨在解决api响应中包含多个json对象但缺乏标准数组封装和逗号分隔的非规范情况。我们将深入探讨一种基于行内容特征识别json对象边界的python解析策略,通过示例代码演示如何将这些独立且无分隔符的json字符串准确地分割并解析为独立的python字典列表,确保数据能够被正确处理和利用。

在与各种API交互时,我们通常期望接收到符合RFC 8259标准的JSON响应。然而,在某些特殊场景下,API可能返回一种非标准的JSON结构,其中包含多个独立的JSON对象,但这些对象既没有被包裹在一个外层数组 [] 中,也没有通过逗号 , 进行分隔。它们可能只是简单地一个接一个地拼接在一起,如下所示:

{
  "key1": "value1",
  "key2": "value2"
}
{
  "key3": "value3",
  "key4": "value4"
}

直接使用 json.loads() 解析此类字符串会导致 json.JSONDecodeError,因为整个字符串不构成一个有效的JSON文档(既不是单个对象也不是单个数组)。本教程将介绍一种在Python中有效解析此类非标准响应的策略。

理解非标准JSON结构

上述非标准结构的核心挑战在于缺乏明确的分隔符。每个JSON对象都以 { 开始,以 } 结束。当一个JSON对象结束后,下一个JSON对象可能紧随其后开始。这种模式提供了一个关键线索:一个对象的结束符 } 后面紧跟着下一个对象的开始符 {,通常在不同的行上。我们可以利用这一特征来识别对象之间的边界。

核心解析策略

我们的策略是逐行读取原始响应数据,并寻找表示一个JSON对象结束和另一个JSON对象开始的特定行模式。具体来说,当遇到一行内容仅为 } 且紧接着下一行内容仅为 { 时,这便是一个对象边界的信号。通过这种方式,我们可以将原始的非标准字符串分割成多个独立的、有效的JSON字符串片段,然后对每个片段单独进行解析。

美图AI开放平台 美图AI开放平台

美图推出的AI人脸图像处理平台

美图AI开放平台 111 查看详情 美图AI开放平台

Python实现示例

以下Python代码演示了如何应用上述策略来解析此类非标准的多对象JSON响应。

import json

# 示例非标准JSON响应数据
non_standard_json_data = '''
{
"self": "https://example1.com",
"key": "keyOne",
"name": "nameOne",
"emailAddress": "mailOne",
"*atarUrls": {
  "48x48": "https://test.com/secure/user*atar?*atarId=1",
  "24x24": "https://test.com/secure/user*atar?size=small&*atarId=1",
  "16x16": "https://test.com/secure/user*atar?size=xsmall&*atarId=1",
  "32x32": "https://test.com/secure/user*atar?size=medium&*atarId=1"
},
"displayName": "displayNameOne",
"active": true,
"timeZone": "Europe",
"locale": "en_UK"
}
{
"self": "https://example2.com",
"key": "keyTwo",
"name": "nameTwo",
"emailAddress": "mailTwo",
"*atarUrls": {
  "48x48": "https://test.com/secure/user*atar?*atarId=2",
  "24x24": "https://test.com/secure/user*atar?size=small&*atarId=2",
  "16x16": "https://test.com/secure/user*atar?size=xsmall&*atarId=2",
  "32x32": "https://test.com/secure/user*atar?size=medium&*atarId=2"
},
"displayName": "displayNameTwo",
"active": false,
"timeZone": "Europe",
"locale": "en_US"
}
'''

def parse_non_standard_multi_json(raw_data: str) -> list[dict]:
    """
    解析包含多个非标准连接JSON对象的字符串。

    Args:
        raw_data: 包含多个JSON对象的原始字符串。

    Returns:
        一个包含所有解析出的JSON字典的列表。
    """
    parsed_objects = []

    # 将原始数据按行分割,并移除每行首尾的空白字符
    lines = [line.strip() for line in raw_data.splitlines()]

    # 过滤掉空行,确保只处理有效内容行
    lines = [line for line in lines if line]

    current_object_start_index = 0

    for i, line in enumerate(lines):
        # 寻找对象边界:当前行是'{'且前一行是'}'
        if i > 0 and line == "{" and lines[i-1] == "}":
            # 提取前一个完整的JSON对象的所有行
            json_segment_lines = lines[current_object_start_index:i]
            # 将这些行拼接成一个完整的JSON字符串
            json_string = "".join(json_segment_lines)
            try:
                # 解析并添加到结果列表
                parsed_objects.append(json.loads(json_string))
            except json.JSONDecodeError as e:
                print(f"解析JSON片段失败: {e}\n片段内容: {json_string}")
                # 根据实际需求处理错误,例如跳过或记录

            # 更新下一个对象的起始索引
            current_object_start_index = i

    # 处理最后一个JSON对象
    if current_object_start_index < len(lines):
        json_segment_lines = lines[current_object_start_index:]
        json_string = "".join(json_segment_lines)
        try:
            parsed_objects.append(json.loads(json_string))
        except json.JSONDecodeError as e:
            print(f"解析最后一个JSON片段失败: {e}\n片段内容: {json_string}")

    return parsed_objects

# 调用解析函数
result_list = parse_non_standard_multi_json(non_standard_json_data)

# 打印解析结果以验证
print(f"成功解析 {len(result_list)} 个JSON对象:")
for idx, obj in enumerate(result_list):
    print(f"\n--- 对象 {idx + 1} ---")
    print(json.dumps(obj, indent=2, ensure_ascii=False))

代码详解

  1. 导入 json 模块: Python内置的 json 库用于JSON数据的序列化和反序列化。
  2. non_standard_json_data: 这是一个多行字符串,模拟了我们遇到的非标准JSON响应数据。
  3. parse_non_standard_multi_json(raw_data) 函数:
    • parsed_objects = []: 初始化一个空列表,用于存储所有成功解析的JSON字典。
    • lines = [line.strip() for line in raw_data.splitlines()]: 将原始字符串按行分割,并使用 strip() 方法移除每行开头和结尾的空白字符(包括换行符、空格等)。这一步非常关键,因为它确保了 "{" 和 "}" 这样的字符串能够被准确匹配。
    • lines = [line for line in lines if line]: 过滤掉所有空行,避免它们干扰判断逻辑。
    • current_object_start_index = 0: 记录当前正在构建的JSON对象在 lines 列表中的起始行索引。
    • 循环遍历行:
      • for i, line in enumerate(lines): 迭代处理每一行及其索引。
      • if i > 0 and line == "{" and lines[i-1] == "}": 这是核心的边界检测逻辑。它检查:
        • i > 0: 确保不是第一行,因为需要比较前一行。
        • line == "{": 当前行是否为 {。
        • lines[i-1] == "}": 前一行是否为 }。
        • 如果这三个条件都满足,说明我们找到了一个JSON对象的结束和下一个JSON对象的开始,即一个对象边界。
      • 提取和解析片段: 当检测到边界时,从 current_object_start_index 到当前行 i 之间的所有行被认为是前一个完整的JSON对象。
        • json_segment_lines = lines[current_object_start_index:i]: 截取这些行。
        • json_string = "".join(json_segment_lines): 将这些行重新拼接成一个完整的JSON字符串。
        • json.loads(json_string): 使用 json.loads() 解析这个片段,并将其添加到 parsed_objects 列表中。
        • current_object_start_index = i: 更新 current_object_start_index 为当前行 i,为下一个JSON对象的解析做准备。
      • 错误处理: try-except json.JSONDecodeError 块用于捕获在解析单个JSON片段时可能发生的错误,提高了程序的健壮性。
    • 处理最后一个JSON对象: 循环结束后,current_object_start_index 到 lines 列表末尾的所有行构成了最后一个JSON对象。需要单独处理它,以确保所有对象都被解析。

注意事项与最佳实践

  1. 数据格式的严格性: 此方法高度依赖于原始数据中 } 和 { 必须单独成行且紧密相连的模式。如果JSON对象内部的字符串值或键包含了 } 或 {,或者格式有其他变体(例如,} 和 { 不在独立行,或者中间有其他非空字符),此方法可能需要调整甚至失效。因此,在实际应用前,务必仔细检查非标准JSON响应的实际格式。
  2. 空白字符处理: line.strip() 和过滤空行是至关重要的。如果原始数据中 } 或 { 前后存在不必要的空白字符,或者它们与JSON内容混杂在同一行,解析逻辑将受到影响。
  3. 错误处理: 在生产环境中,应加强 json.JSONDecodeError 的处理。例如,可以记录错误片段、跳过损坏的对象,或者抛出自定义异常,以便上层应用能够感知并处理数据不完整的情况。
  4. 性能考量: 对于非常大的响应数据,逐行处理并多次拼接字符串可能会有一定的性能开销。如果性能成为瓶颈,可以考虑使用正则表达式进行更高效的分割,但正则表达式的编写会更加复杂,且需要确保其鲁棒性。
  5. API规范化: 最根本的解决方案是与API提供方沟通,请求他们返回符合标准的JSON格式(例如,将所有对象封装在一个JSON数组中)。这不仅简化了客户端解析逻辑,也提高了数据的互操作性和可靠性。

总结

尽管API返回非标准JSON格式是一种不理想的情况,但通过本教程介绍的基于行内容特征识别边界的策略,我们能够有效地在Python中解析此类数据。该方法的核心在于将原始数据分割成多个独立的、可解析的JSON字符串片段,然后逐一处理。理解这种策略及其潜在的局限性,将有助于开发者在面对各种复杂数据格式时,构建更健壮和灵活的数据处理方案。

以上就是处理非标准多对象JSON响应:Python解析策略与实践的详细内容,更多请关注其它相关文章!


# js  # json  # 正则表达式  # app  # ai  # json数组  # python  # 网站建设的通知  # 网站建设专业读后感  # 温州企业营销推广制作中心  # 马鞍山网站优化哪家强  # 如何做香港网站网址推广  # 专利营销推广案例分析题  # 网站建设方案概述  # 批量查询关键词排名  # 欧美篮球推广网站大全  # 竞价网站建设怎么样  # 移除  # 跳过  # 仅为  # 管理系统  # 原始数据  # 此类  # 美图  # 多个  # 非标准 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: C++如何进行游戏物理模拟_使用Box2D库为C++游戏添加2D物理效果  在Go开发中优雅管理ListenAndServe进程:GoSublime集成方案  漫蛙漫画官方主页入口 漫蛙MANWA网页直达访问链接  Golang如何通过reflect操作map_Golang reflect map操作与遍历技巧  J*aScript数据结构转换:将对象数组按类别分组  Promise错误处理:在catch后终止链式then执行的策略  React/Next.js中实现列表项的动态选择与移动  在Go Martini框架中高效服务动态生成图像的实践指南  淘宝支付提示失败如何解决 淘宝支付流程优化方法  LINQ to XML为何解析失败? 深入理解C# XDocument的异常处理  腾讯视频怎么举报不良内容_腾讯视频内容举报流程与违规信息处理方法  C++如何解决segmentation fault_C++段错误调试与原因分析  J*a如何使用AtomicInteger控制计数_J*a无锁计数器性能分析  妖精漫画网页版登录入口免费_妖精漫画官网主页直接阅读漫画  学习通网页版快速入口 学习通官网网页版直接打开  微博网页版怎么开启两步验证_微博网页版账号安全两步验证设置方法  PrimeNG Sidebar背景色自定义指南:CSS覆盖与主题化实践  c++中的std::basic_string的SSO优化_c++短字符串优化深度解析  J*aScript中正确使用querySelectorAll与复杂CSS选择器  Node.js CSV 数据处理:基于字段值条件过滤整条记录的策略  漫蛙2(台版)官方入口地址 漫蛙2(台版)正版漫画网页端  Django表单验证失败时保留用户输入数据的最佳实践  如何优雅地解决Livewire文件上传难题?SpatieLivewireFilepond让一切变得简单  谷歌浏览器如何快速清除某个网站的数据_Chrome网站缓存清理方法  支付宝如何设置安全保护_支付宝安全设置的全面教程  今日头条怎么同步内容到抖音_今日头条内容同步到抖音教程  Python中如何避免重复条件判断:利用数据结构实现动态逻辑  小米Civi 4录制视频过暗_小米Civi 4亮度优化  解决Python单元测试中Mock异常方法调用计数为零的问题  QQ邮箱电脑版登录入口_QQ邮箱官方网站登录平台  C++ vector二维数组定义_C++ vector of vector用法  DLsite中文平台入口 DLsite官网内容在线查看  J*aScript数组对象转换:按指定键分组与值收集  Django模型中自动计算可用余额的实现方法  谷歌浏览器一键优化方案_谷歌浏览器直达主页极速不卡版  如何在低配置电脑上搭建轻量级J*a环境_占用更小的环境选择技巧  微信群消息显示延迟如何解决 微信群消息刷新优化方法  如何在Promise链中优雅地中断后续then执行  汽水音乐在线解析 汽水音乐在线解析入口  微信语音通话掉线如何解决 微信语音通话稳定优化方法  神庙逃亡小游戏在线玩 神庙逃亡小游戏入口  CSS Flexbox如何实现多行排列_flex-wrap wrap自动换行显示  J*a里如何使用forEach遍历Map_Map遍历方法说明  mc.js游戏直达 mc.js网页免下载版本秒进地址  React/Next.js中实现列表项的动态移动与状态管理:兼论唯一键的重要性  俄罗斯Yandex免登录入口_Yandex搜索引擎官网一键直达  谷歌邮箱注册显示错误Gmail服务器异常与延迟处理  c++ 命名空间怎么用 c++ namespace使用指南  处理Kafka消费者会话超时:深入理解消息处理语义与幂等性  飞书妙记怎样用语音转文字速记_飞书妙记用语音转文字速记【速记方法】 

搜索