
本教程旨在解决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字符串片段,然后对每个片段单独进行解析。
立即学习“Python免费学习笔记(深入)”;
以下Python代码演示了如何应用上述策略来解析此类非标准的多对象JSON响应。
import json
# 示例非标准JSON响应数据
non_standard_json_data = '''
{
"self": "https://example1.com",
"key": "keyOne",
"name": "nameOne",
"emailAddress": "mailOne",
"avatarUrls": {
"48x48": "https://test.com/secure/useravatar?avatarId=1",
"24x24": "https://test.com/secure/useravatar?size=small&avatarId=1",
"16x16": "https://test.com/secure/useravatar?size=xsmall&avatarId=1",
"32x32": "https://test.com/secure/useravatar?size=medium&avatarId=1"
},
"displayName": "displayNameOne",
"active": true,
"timeZone": "Europe",
"locale": "en_UK"
}
{
"self": "https://example2.com",
"key": "keyTwo",
"name": "nameTwo",
"emailAddress": "mailTwo",
"avatarUrls": {
"48x48": "https://test.com/secure/useravatar?avatarId=2",
"24x24": "https://test.com/secure/useravatar?size=small&avatarId=2",
"16x16": "https://test.com/secure/useravatar?size=xsmall&avatarId=2",
"32x32": "https://test.com/secure/useravatar?size=medium&avatarId=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))
尽管API返回非标准JSON格式是一种不理想的情况,但通过本教程介绍的基于行内容特征识别边界的策略,我们能够有效地在Python中解析此类数据。该方法的核心在于将原始数据分割成多个独立的、可解析的JSON字符串片段,然后逐一处理。理解这种策略及其潜在的局限性,将有助于开发者在面对各种复杂数据格式时,构建更健壮和灵活的数据处理方案。
以上就是处理非标准多对象JSON响应:Python解析策略与实践的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号