脚本专家 发表于 2026-6-15 09:00:01

Python解析非标准JSON:5种场景与json5/ast.literal_eval方案对比

在日常开发中,从日志、配置或第三方接口拿到的JSON数据往往不符合标准规范。Python自带的json.loads()遇到单引号、末尾逗号、无引号键名或注释会直接抛出异常。本文整理5种常见非标准场景,并提供从ast.literal_eval到json5的完整解决方案,帮你快速清洗数据。

场景一:单引号+末尾逗号
手写配置或API日志中经常出现这种格式:


data = "{'name': 'Tom', 'age': 18,}"


方案1:ast.literal_eval(推荐轻量场景)

import ast
result = ast.literal_eval(data)
# {'name': 'Tom', 'age': 18}

ast.literal_eval能安全解析Python字面量,包括单引号、末尾逗号、True/False/None。但它不能解析真正的JSON扩展(如null、true)。

方案2:正则替换+json.loads

import json, re
def fix_json(s):
    s = re.sub(r"(?<!\\)'", '"', s)
    s = re.sub(r',\s*([\]\}])', r'\1', s)
    return json.loads(s)
result = fix_json(data)

这种方法灵活但正则容易漏掉字符串内部的引号,复杂场景建议慎用。

场景二:键名未加引号

data = '{name: "Tom", age: 18}'

方案:使用demjson3或json5

pip install demjson3
import demjson3
result = demjson3.decode(data)

或使用更标准的json5:

pip install json5
import json5
result = json5.loads(data)

json5是JSON5格式的Python实现,支持无引号键名、单引号、注释、尾随逗号等所有非标准特性,且维护活跃。

场景三:包含注释的JSON
某些配置文件会夹杂//或/* */注释:

{
    "name": "Tom", // 用户名
    "age": 18
}

方案1:正则清除注释

import re
def strip_comments(s):
    s = re.sub(r'//.*', '', s)
    s = re.sub(r'/\*.*?\*/', '', s, flags=re.DOTALL)
    return s

清除后再用json.loads解析。
方案2:直接用json5一步到位

import json5
with open('config.json5', 'r') as f:
    data = json5.load(f)


场景四:JavaScript风格的特殊值
数据中包含undefined、NaN、Infinity:

{"value": undefined, "num": NaN}

方案:demjson3能自动转换(undefined→None,NaN→nan,Infinity→inf)。json5同样支持。

场景五:十六进制数字(如0xFF)
标准JSON不支持,但json5可以解析。

方案对比
- json.loads:仅标准JSON,快但严格。
- ast.literal_eval:Python字面量,安全无依赖,不能识别null/true/false。
- demjson3:功能较全,但社区维护少,新版Python可能不兼容。
- json5:语法标准、功能全面、持续维护,推荐作为主力方案。
- 正则替换:适合简单一次性清洗,容易出错。

实践建议
1. 如果数据来源固定且简单(如手写配置),优先用ast.literal_eval。
2. 数据格式未知且复杂,直接上json5,开箱即用。
3. 生产环境对性能敏感:先用json5清洗并保存为标准JSON,后续用json.loads。
4. 永远不要信任外部JSON,尽量要求对方输出规范格式。

总结
非标准JSON的本质是生产方与消费方对格式定义不一致。Python生态提供了从轻量ast.literal_eval到全面json5的多种方案,选哪个取决于数据有多“脏”。json5是目前最推荐的折中选择——既有广泛的标准支持,又能覆盖绝大多数异常情况。

热心网友6 发表于 2026-6-15 09:10:00

Re: Python解析非标准JSON:5种场景与json5/ast.literal_eval方案对比

感谢分享,这篇文章非常实用!我平时也经常遇到手写配置里单引号加末尾逗号的情况,之前一直用正则硬改,确实容易翻车。你提到的ast.literal_eval和json5的对比很清楚,尤其是性能敏感时先清洗再存标准JSON的思路很实在。以后遇到带注释的配置文件,直接上json5省心多了。

热心网友7 发表于 2026-6-16 17:25:00

Re: Python解析非标准JSON:5种场景与json5/ast.literal_eval方案对比

感谢楼主这么系统地梳理!平时用Python处理日志里的“脏”JSON确实经常踩坑——特别是单引号和尾逗号,每次都要手动替换。 我之前一直用ast.literal_eval处理简单的手写配置,确实轻量安全,但遇到null/true时直接报错,后来换成json5确实一劳永逸。楼主提到的“先用json5清洗再转标准JSON缓存”这个思路很棒,适合高性能场景。 想请教两个小细节: 1. 正则替换单引号时,如果字符串内部有转义的单引号(比如`"Tom\'s"`),楼主的正则会不会误替换?有没有更健壮的写法? 2. json5解析NaN时,Python的float('nan')是否会影响后续计算的可预测性(比如传给数据库或序列化)? 再次感谢分享,收藏了!

热心网友5 发表于 2026-6-16 20:00:00

Re: Python解析非标准JSON:5种场景与json5/ast.literal_eval方案对比

感谢楼主的详细总结!最近正好被一个带注释的配置文件折腾过,试了正则清理,但注释内容里偶尔混着特殊字符就翻车了。看了你的对比准备直接上json5了,一步到位确实省心。另外问一下,json5对性能的影响大吗?如果处理几百M的大文件,会不会比标准json慢很多?
页: [1]
查看完整版本: Python解析非标准JSON:5种场景与json5/ast.literal_eval方案对比