解析非标准多对象JSON响应的Python教程


解析非标准多对象JSON响应的Python教程

本教程旨在解决接收到由多个独立json对象直接拼接而成,而非封装在数组或以逗号分隔的非标准json响应数据。我们将介绍一种基于行检测的python方法,通过识别相邻的`}`和`{`字符序列来精确分割并解析每个独立的json对象,从而有效处理此类特殊数据格式。

在数据交换中,JSON(J*aScript Object Notation)因其轻量级和易于解析的特性而广受欢迎。通常,当我们需要传输多个JSON对象时,它们会被封装在一个JSON数组中,例如 [{...}, {...}],或者以逗号分隔。然而,在某些特定场景下,我们可能会遇到一种非标准的JSON响应格式,即多个独立的JSON对象直接拼接在一起,既没有外部的数组方括号,也没有对象之间的逗号分隔符。这种格式 {...}{...} 无法直接使用标准的 json.loads() 方法进行解析,因为它不构成一个合法的JSON文档。

1. 理解非标准JSON响应格式

标准的JSON规范要求一个JSON文档要么是一个对象,要么是一个数组。当服务器返回多个JSON对象时,它们通常会像这样组织:

[
  {
    "id": 1,
    "name": "Object One"
  },
  {
    "id": 2,
    "name": "Object Two"
  }
]

然而,本教程所讨论的场景是接收到以下形式的数据:

{
"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"
}

这种格式在Python中直接使用 json.loads() 会导致 json.JSONDecodeError,因为它被视为一个包含多个根级别元素的无效JSON字符串。

2. 基于行检测的解析策略

要成功解析这种非标准格式,我们需要一种方法来识别每个独立JSON对象的边界。观察上述数据结构,可以发现一个关键模式:一个JSON对象的结束标记 } 紧接着下一行就是下一个JSON对象的开始标记 {。我们可以利用这个特征来手动分割整个响应字符串。

核心思路如下:

  1. 将整个响应字符串按行分割成一个列表。
  2. 遍历这些行,寻找 } 字符出现在某一行,并且紧随其后的下一行是 { 字符。
  3. 当检测到这种模式时,意味着我们找到了一个JSON对象的结束和下一个JSON对象的开始,从而可以提取出当前已收集的行,将其拼接成一个完整的JSON字符串,并使用 json.loads() 进行解析。
  4. 重复此过程,直到所有对象都被解析。

3. Python实现步骤与代码示例

以下是使用Python实现此解析策略的详细步骤和代码:

首先,准备我们的非标准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"
}
'''

接下来是解析代码:

PHP高级程序设计 模式 框架与测试(中文高清PDF版) PHP高级程序设计 模式 框架与测试(中文高清PDF版)

享有盛誉的PHP高级教程,Zend Framework核心开发人员力作,深入设计模式、PHP标准库和JSON 。   今天,PHP已经是无可争议的Web开发主流语言。PHP 5以后,它的面向对象特性也足以与J*a和C#相抗衡。然而,讲述PHP高级特性的资料一直缺乏,大大影响了PHP语言的深入应用。   本书填补了这一空白。它专门针对有一定经验的PHP程序员,详细讲解了对他们最为重要的主题

PHP高级程序设计 模式 框架与测试(中文高清PDF版) 455 查看详情 PHP高级程序设计 模式 框架与测试(中文高清PDF版)
from json import loads, dumps

jlist = [] # 用于存储解析后的JSON对象
k = 0      # 标记当前JSON对象开始的行索引

# 将原始数据按行分割
lines = data.splitlines()

# 遍历所有行,查找对象边界
for i, line in enumerate(lines):
    # 检查当前行是否为 '{' 且前一行是否为 '}'
    # i > 0 确保不是第一行,避免索引越界
    if i > 0 and line.strip() == "{" and lines[i-1].strip() == "}":
        # 找到了一个对象边界,将从 k 到 i 的行拼接成一个JSON字符串并解析
        json_str_segment = "".join(lines[k:i])
        jlist.append(loads(json_str_segment))
        k = i # 更新 k 为新对象的起始行

# 处理最后一个JSON对象
# 循环结束后,从 k 到末尾的行构成了最后一个JSON对象
json_str_segment = "".join(lines[k:])
jlist.append(loads(json_str_segment))

# 打印解析后的每个JSON对象以验证
for j_obj in jlist:
    print(dumps(j_obj, indent=2, ensure_ascii=False))
    print("-" * 30) # 分隔符,便于查看

代码解释:

  • lines = data.splitlines(): 将多行字符串 data 分割成一个字符串列表,每个元素代表一行。
  • for i, line in enumerate(lines): 使用 enumerate 同时获取行索引 i 和行内容 line。
  • if i > 0 and line.strip() == "{" and lines[i-1].strip() == "}": 这是核心的边界检测逻辑。
    • i > 0: 确保我们不是在处理第一行,因为需要比较 lines[i-1]。
    • line.strip() == "{": 检查当前行去除空白后是否为 {。
    • lines[i-1].strip() == "}": 检查前一行去除空白后是否为 }。
    • .strip() 方法用于移除行首和行尾的空白字符,增加了对数据格式中可能存在的额外空白的容错性。
  • json_str_segment = "".join(lines[k:i]): 当检测到边界时,将从 k(当前JSON对象起始行)到 i(当前JSON对象结束行,但不包含 i)的所有行拼接起来,形成一个完整的JSON字符串。
  • jlist.append(loads(json_str_segment)): 使用 json.loads() 解析拼接好的字符串,并将其添加到 jlist 中。
  • k = i: 更新 k 为当前行的索引 i,表示下一个JSON对象将从这里开始。
  • json_str_segment = "".join(lines[k:]): 循环结束后,最后一部分数据(从 k 到 lines 列表的末尾)构成了最后一个JSON对象,需要单独解析。

4. 运行结果展示

执行上述代码后,你将看到每个独立的JSON对象都被正确解析并格式化打印出来:

{
  "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"
}
------------------------------

5. 注意事项与健壮性考量

  • 格式依赖性: 此方法高度依赖于 } 和 { 字符在独立行上且彼此相邻的特定模式。如果JSON对象内部的字符串值恰好包含 } 或 { 并在行尾/行首,或者 } 和 { 不在单独的行上(例如,{"a":1}{"b":2} 这种单行拼接),此方法可能需要调整甚至失效。

  • 空白字符: 代码中使用了 .strip() 来处理行首尾的空白,这增强了对格式变化的容错性。但如果 } 或 { 周围有其他非空白字符,则此方法将不适用。

  • 错误处理: json.loads() 在遇到任何无效的JSON片段时都会抛出 json.JSONDecodeError 异常。在生产环境中,强烈建议将 loads() 调用封装在 try-except 块中,以便优雅地处理可能出现的解析错误,例如:

    try:
        jlist.append(loads(json_str_segment))
    except json.JSONDecodeError as e:
        print(f"Error decoding JSON segment: {e}")
        print(f"Problematic segment: {json_str_segment}")
        # 可以选择跳过此段或进行其他错误处理
  • 性能: 对于非常大的文件,按行读取和拼接字符串可能会有一定的性能开销。但对于大多数常见的JSON响应大小,这种方法是高效且可接受的。

  • 替代方案: 如果数据格式更加复杂或不规则,例如 }{ 不总是出现在独立行上,或者对象之间有其他非JSON内容,那么可能需要更强大的文本处理工具,如正则表达式 (re 模块) 来匹配和提取每个JSON对象。

6. 总结

当面对非标准的多个JSON对象直接拼接的响应数据时,直接使用 json.loads() 是行不通的。通过分析其独特的结构特征,即 } 紧接着 { 的行模式,我们可以设计一个基于行检测的Python解析策略。此方法能够有效地将整个响应字符串分割成独立的、可解析的JSON片段,从而成功提取出所有数据。在实际应用中,务必考虑数据格式的稳定性和可能出现的异常情况,并添加相应的错误处理机制,以确保程序的健壮性。理解并适应各种数据格式是处理外部数据时的关键技能。

以上就是解析非标准多对象JSON响应的Python教程的详细内容,更多请关注其它相关文章!


# python  # 装在  # 迭代  # 是一个  # 数据结构  # 程序设计  # 数据格式  # 迷思  # 遍历  # 非标准  # json数组  # ai  # 工具  # app  # 正则表达式  # json  # js  # java  # javascript  # 多个  # 前端网站建设和维护  # 新建网站推广怎么填  # 国产智能seo  # 长春网站建设的基本流程  # 灵山租房网站建设  # 黄浦营销推广简单吗知乎  # 新密建设局网站  # 龙海网站建设价格  # 怎么制作二手车网站推广  # 年度营销推广目标 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 优化推广96088 】 【 技术知识133117 】 【 IDC资讯59369 】 【 网络运营7196 】 【 IT资讯61894


相关推荐: Leaflet地图弹出窗口图片动态显示:避免缺失图标的专业指南  如何在CSS中使用absolute实现登录弹窗居中_transform translate结合  win11如何诊断DirectX问题 Win11运行dxdiag工具排查显卡故障【排错】  漫蛙manwa官网浏览入口_漫蛙漫画网页版访问链接  在XML中嵌入二进制数据(如图片)的最佳实践是什么? Base64编码与解析注意事项  红手指专业版app注册教程  汽水音乐官网网页版入口 汽水音乐官网网页版在线入口  顺丰速运官网查询入口 顺丰物流查询官网入口链接  秋风萧瑟洪波涌起中的萧瑟指的是什么  解决Pandas DataFrame高度碎片化警告:高效创建多列的策略  太平年在哪个平台播出  斯宾塞称XGP云游戏“蒸蒸日上”:正在构建一个游戏从未如此唾手可得的未来  AO3永久镜像入口开放_AO3最新网址兼容所有浏览器  《知到》打卡课程方法  邦丰播放器频道搜索设置  铁路12306座位怎么选_12306官方选座操作方法  《淘票票》添加到苹果钱包教程  sublime怎么在文件中显示代码结构大纲_sublime符号列表功能  Lar*el Socialite单设备登录策略:实现用户唯一会话管理  如何用Golang优化微服务间请求性能_Golang 微服务请求性能优化方法  PHP实现等比数列:构建数组元素基于前一个值递增的方法  在J*a中如何实现在线问答与评分系统_问答评分项目开发方法说明  解决Flex容器横向滚动内容截断与偏移问题  RxJS中如何高效地在一个函数内处理和合并多个数据集合  包子漫画官网链接官方地址 包子漫画在线观看官网首页入口  《三国:谋定天下》平民全阶段通用阵容  繁花漫画使用教程  CSS过渡与滚动滚动事件结合应用_scroll与transition动画  铁拳8在线玩 铁拳8在线秒玩入口  PySimpleGUI中实现键盘按键与按钮事件绑定教程  《淘宝联盟》推广自己的店铺方法  mysql中如何配置字符集和排序规则_mysql字符集排序配置  《百果园》充值余额方法  Sublime怎么自动添加CSS前缀_Sublime安装Autoprefixer插件  J*aScript实现网页表单实时输入字段比较与验证教程  《饿了么》拼好饭点外卖教程2025  微信朋友圈怎么设置三天可见 微信朋友圈设置指定天数可见步骤【教程】  谷歌邮箱官方入口链接 谷歌邮箱网页版电脑端快速登录  《盗墓笔记手游》技能介绍  在J*a中如何实现类的继承与方法重用_OOP继承方法重用技巧分享  苹果SE如何开启单手模式_苹果SE单手操作功能  淘口令快速解析技巧  搜狗浏览器如何查找页面中的文字 搜狗浏览器Ctrl+F页面搜索功能  J*a实现任务清单管理_集合框架综合入门练手  163邮箱网页版官方登录入口 163邮箱网页版访问页面  windows10怎么更改下载路径_windows10默认存储位置修改教程  12306APP选座怎么选充电位置_12306APP带充电插座座位选择方法与技巧  菜鸟驿站的取件码忘了怎么办 手机快速查询指南  《健康大兴》注册方法介绍  GBA模拟器手柄按键设置 

 2025-12-05

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

运城市盐湖区信雨科技有限公司


运城市盐湖区信雨科技有限公司

运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。

 8156699

 13765294890

 8156699@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.