Python解析不规则JSON数据的实战技巧

 更新时间:2026年01月27日 09:39:52   作者:大黄评测  
在真实世界的数据处理中,我们很少遇到教科书式的标准 JSON,文将为你提供一套从温和修复到强力解析的完整工具箱,用 Python 轻松驯服这些野性数据,有需要的小伙伴可以了解下

在真实世界的数据处理中,我们很少遇到教科书式的标准 JSON。更多时候,面对的是:

  • 单引号代替双引号
  • 末尾多出逗号
  • 键名未加引号(如 {name: "Alice"}
  • 混合了注释(// 这是注释
  • 嵌套结构缺失或类型错乱(字符串里藏了 JSON 片段)
  • 甚至根本不是合法 JSON,而是 JavaScript 对象字面量(JS Object Literal)

这类“不规则 JSON”无法被 Python 内置的 json.loads() 直接解析,强行使用会抛出 JSONDecodeError。但别急——本文将为你提供一套从温和修复到强力解析的完整工具箱,用 Python 轻松驯服这些“野性”数据。

一、场景1:轻微格式错误(单引号、尾逗号等)

典型数据

{
  'name': 'Alice',
  'age': 30,
  'tags': ['a', 'b',],
}

解法:使用ast.literal_eval(仅限 Python 字面量)

如果数据本质是 Python 字典/列表字面量(而非严格 JSON),可尝试:

import ast

dirty_str = "{'name': 'Alice', 'age': 30, 'tags': ['a', 'b',]}"
try:
    data = ast.literal_eval(dirty_str)
    print(data)  # {'name': 'Alice', 'age': 30, 'tags': ['a', 'b']}
except (ValueError, SyntaxError) as e:
    print("无法解析为 Python 字面量")

注意:ast.literal_eval 只支持 str, bytes, int, float, list, dict, tuple, bool, None,不支持 NaNInfinity 等。

二、场景2:含注释、尾逗号、键无引号(类 JS 对象)

典型数据

{
  // 用户信息
  name: "Bob",
  age: 25,
  hobbies: [
    "coding",
    "gaming",  // 末尾逗号
  ],
}

解法:使用json5库(推荐!)

JSON5 是 JSON 的扩展,支持注释、单引号、尾逗号、无引号键等,完美兼容 JavaScript 风格对象。

安装:

pip install json5

使用:

import json5

with open('config.js', 'r', encoding='utf-8') as f:
    data = json5.load(f)  # 或 json5.loads(string)

print(data['name'])  # Bob

优点:安全、标准、广泛用于前端配置文件(如 .babelrc, tsconfig.json 变体)。

三、场景3:字符串中嵌套未转义的 JSON 片段

典型数据

{
  "log": "User {"id": 123, "action": "login"} performed"
}

你可能想提取内部的 {"id": 123, ...},但它被包裹在字符串中。

解法:正则 + 递归解析

import json
import re

def extract_and_parse_nested_json(text):
    # 匹配最外层的 {...},但需确保是完整 JSON 对象
    pattern = r'{(?:[^{}]|(?R))*}'  # 递归正则(Python 不支持 (?R),改用循环)
    
    # 更稳健的做法:逐字符扫描括号匹配
    def find_outer_braces(s):
        stack = 0
        start = -1
        for i, c in enumerate(s):
            if c == '{':
                if stack == 0:
                    start = i
                stack += 1
            elif c == '}':
                stack -= 1
                if stack == 0 and start != -1:
                    return s[start:i+1]
        return None

    nested = find_outer_braces(text)
    if nested:
        try:
            return json.loads(nested)
        except json.JSONDecodeError:
            return None
    return None

log_str = 'User {"id": 123, "action": "login"} performed'
inner = extract_and_parse_nested_json(log_str)
print(inner)  # {'id': 123, 'action': 'login'}

四、场景4:完全非结构化,但有规律可循

比如日志文件中的混合内容:

INFO: {user: "Tom", status: ok}
ERROR: Failed to parse {data: [1,2,,3]}

解法:先用正则提取疑似 JSON 片段,再用容错解析器

结合 json5 + 异常捕获:

import json5
import re

log_line = 'ERROR: Failed to parse {data: [1,2,,3]}'

# 提取花括号包围的内容
match = re.search(r'{.*}', log_line)
if match:
    candidate = match.group()
    try:
        data = json5.loads(candidate)
        print("Parsed:", data)
    except Exception as e:
        print("Still invalid:", e)

提示:对于 [, ,] 这类空元素,json5 也支持(视为 null)。

五、终极武器:自定义解析器 or LLM 辅助(慎用)

若数据极度混乱(如混合 HTML、自定义 DSL),可考虑:

  • 使用 larkply 构建自定义语法解析器;
  • 用大模型(如本地 LLM)将“脏数据”重写为合法 JSON(适合低频、高价值场景)。

但绝大多数情况,json5 + 正则清洗 + 异常处理 已足够覆盖。

最佳实践建议

  • 优先用 json5:它能解决 90% 的“类 JSON”问题;
  • 不要用 eval() :极其危险,可能执行任意代码;
  • 记录解析失败样本:用于后续规则优化;
  • 在数据入口 做标准化:若可控,推动上游输出合法 JSON。

结语

不规则 JSON 不是“错误”,而是现实世界的常态。Python 生态提供了从轻量级(ast)到工业级(json5)的多种工具,关键在于识别数据“脏”在哪一层,然后选择匹配的清洗策略。

记住:解析不是目的,可靠地获取结构化信息才是。用对工具,那些看似混乱的字符串,终将成为你数据管道中的清晰字段。

到此这篇关于Python解析不规则JSON数据的实战技巧的文章就介绍到这了,更多相关Python解析JSON数据内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 基于python实现蓝牙通信代码实例

    基于python实现蓝牙通信代码实例

    这篇文章主要介绍了基于python实现蓝牙通信代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11
  • Python列表和元组的定义与使用操作示例

    Python列表和元组的定义与使用操作示例

    这篇文章主要介绍了Python列表和元组的定义与使用操作,结合实例形式分析了Python中列表和元组的功能、区别、定义及使用方法,需要的朋友可以参考下
    2017-07-07
  • 利用打码兔和超人打码自封装的打码类分享

    利用打码兔和超人打码自封装的打码类分享

    打码是利用人工智能大量输入验证码的意思,这里提供一个自封装的打码类,需要的朋友可以参考下
    2014-03-03
  • Python获取当前目录下所有文件的6种方法总结

    Python获取当前目录下所有文件的6种方法总结

    这篇文章主要给大家介绍了关于Python获取当前目录下所有文件的6种方法,要获取当前目录下的所有目录,可以使用Python内置的os模块中的listdir()函数和isdir()函数,需要的朋友可以参考下
    2023-08-08
  • 浅谈python的输入输出,注释,基本数据类型

    浅谈python的输入输出,注释,基本数据类型

    这篇文章主要介绍了python的输入输出,注释,基本数据类型,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04
  • 用selenium解决滑块验证码的实现步骤

    用selenium解决滑块验证码的实现步骤

    验证码作为一种自然人的机器人的判别工具,被广泛的用于各种防止程序做自动化的场景中,下面这篇文章主要给大家介绍了关于用selenium解决滑块验证码的实现步骤,需要的朋友可以参考下
    2023-02-02
  • Python如何用*打印正三角、倒三角、等边三角形、菱形及空心菱形

    Python如何用*打印正三角、倒三角、等边三角形、菱形及空心菱形

    这篇文章主要给大家介绍了关于Python如何用*打印正三角、倒三角、等边三角形、菱形及空心菱形的相关资料,提供了每种形状的实现代码和输出结果,需要的朋友可以参考下
    2025-05-05
  • Python工具PDB调试器的使用方法详解

    Python工具PDB调试器的使用方法详解

    还记得你是如何进行代码调试的吗?有人会说,我是添加一些输出语句,有人说,我是使用IDE自带的设置断点功能,当然都没有错,只是看哪个更合适,更能提升效率,但这都不是我们今天讲的重点,今天的重点是Python中PDB调试器的使用方法,需要的朋友可以参考下
    2023-11-11
  • Python 实现文件的全备份和差异备份详解

    Python 实现文件的全备份和差异备份详解

    这篇文章主要介绍了Python 实现文件的全备份和差异备份详解的相关资料,需要的朋友可以参考下
    2016-12-12
  • Python中两个列表数字相加的4种方法示例详解

    Python中两个列表数字相加的4种方法示例详解

    这篇文章主要给大家介绍了关于Python中两个列表数字相加的4种方法,我们可以使用Python的加号和减号运算符来实现两个数字的相加减,需要的朋友可以参考下
    2023-08-08

最新评论