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

Written by

in

文章目录
  • 典型数据: { ‘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,不支持 NaN、Infinity 等。
  • 典型数据: { // 用户信息 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 变体)。
  • 典型数据: { “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’}
  • 比如日志文件中的混合内容: 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)。
  • 若数据极度混乱(如混合 HTML、自定义 DSL),可考虑: 使用 lark、ply 构建自定义语法解析器; 用大模型(如本地 LLM)将“脏数据”重写为合法 JSON(适合低频、高价值场景)。 但绝大多数情况,json5 + 正则清洗 + 异常处理 已足够覆盖。
  • 优先用 json5:它能解决 90% 的“类 JSON”问题; 不要用 eval() :极其危险,可能执行任意代码; 记录解析失败样本:用于后续规则优化; 在数据入口 做标准化:若可控,推动上游输出合法 JSON。
  • 不规则 JSON 不是“错误”,而是现实世界的常态。Python 生态提供了从轻量级(ast)到工业级(json5)的多种工具,关键在于识别数据“脏”在哪一层,然后选择匹配的清洗策略。 记住:解析不是目的,可靠地获取结构化信息才是。用对工具,那些看似混乱的字符串,终将成为你数据管道中的清晰字段。 到此这篇关于Python解析不规则JSON数据的实战技巧的文章就介绍到这了,更多相关Python解析JSON数据内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客! 您可能感兴趣的文章: python进阶之JSON数据解析完整示例 Python3入门之JSON数据解析全面学习教程 Python处理JSON文件的完整流程(读取、解析、修改和保存) Python处理JSON的四大函数全解析(load/loads/dump/dumps) Python解析JSON数据的示例代码 Python JSON数据解析过程(最新推荐)
  • 目录
    • 一、场景1:轻微格式错误(单引号、尾逗号等)
    • 二、场景2:含注释、尾逗号、键无引号(类 JS 对象)
    • 三、场景3:字符串中嵌套未转义的 JSON 片段
    • 四、场景4:完全非结构化,但有规律可循
    • 五、终极武器:自定义解析器 or LLM 辅助(慎用)
    • 最佳实践建议
    • 结语

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

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

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

    典型数据

    {
      '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 等。

    典型数据

    {
      // 用户信息
      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 变体)。

    典型数据

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

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

    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)。

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

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

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

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

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

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

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

    您可能感兴趣的文章:

    • python进阶之JSON数据解析完整示例
    • Python3入门之JSON数据解析全面学习教程
    • Python处理JSON文件的完整流程(读取、解析、修改和保存)
    • Python处理JSON的四大函数全解析(load/loads/dump/dumps)
    • Python解析JSON数据的示例代码
    • Python JSON数据解析过程(最新推荐)

    站内搜索