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是目前最推荐的折中选择——既有广泛的标准支持,又能覆盖绝大多数异常情况。
Re: Python解析非标准JSON:5种场景与json5/ast.literal_eval方案对比
感谢分享,这篇文章非常实用!我平时也经常遇到手写配置里单引号加末尾逗号的情况,之前一直用正则硬改,确实容易翻车。你提到的ast.literal_eval和json5的对比很清楚,尤其是性能敏感时先清洗再存标准JSON的思路很实在。以后遇到带注释的配置文件,直接上json5省心多了。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')是否会影响后续计算的可预测性(比如传给数据库或序列化)? 再次感谢分享,收藏了!Re: Python解析非标准JSON:5种场景与json5/ast.literal_eval方案对比
感谢楼主的详细总结!最近正好被一个带注释的配置文件折腾过,试了正则清理,但注释内容里偶尔混着特殊字符就翻车了。看了你的对比准备直接上json5了,一步到位确实省心。另外问一下,json5对性能的影响大吗?如果处理几百M的大文件,会不会比标准json慢很多?
页:
[1]