
前言JSON是Web开发中最常用的数据交换格式但现实世界从来不按规范来。你可能遇到过这些情况单引号代替双引号{name: Tom}末尾多了逗号{name: Tom,}键名没加引号{name: Tom}注释混在里面{name: Tom // this is a comment}Python自带的json.loads()遇到这些会直接报错。本文整理了几种常见的非标准JSON场景以及对应的解决方案。场景一单引号 末尾逗号这是最常见的脏数据通常来自手写配置或某些API的日志。importjson data{name: Tom, age: 18,}# 单引号 末尾逗号# json.loads(data) # 报错JSONDecodeError解决方案1用ast.literal_eval推荐importast data{name: Tom, age: 18,}resultast.literal_eval(data)print(result)# {name: Tom, age: 18}ast.literal_eval可以安全地解析Python字面量包括单引号字符串、末尾逗号、True/False/None等。⚠️ 注意它只能解析Python语法能识别的值不能处理真正的JSON扩展。解决方案2先替换再解析importjsonimportredeffix_json(s):# 单引号 → 双引号注意避免替换字符串内部的引号sre.sub(r(?!\\),,s)# 去除末尾逗号sre.sub(r,\s*([\]}]),r\1,s)returnjson.loads(s)data{name: Tom, age: 18,}resultfix_json(data)print(result)这种方式更灵活但正则替换有边界风险复杂场景容易漏。场景二键名未加引号data{name: Tom, age: 18}# 键名没引号不是合法JSON解决方案用demjson3库pipinstalldemjson3importdemjson3 data{name: Tom, age: 18}resultdemjson3.decode(data)print(result)# {name: Tom, age: 18}demjson3是目前处理非标准JSON最强的第三方库支持无引号键名单引号末尾逗号注释//和/* */JavaScript风格的undefined、NaN、Infinity场景三包含注释的JSON某些配置文件会在JSON里加注释这在标准JSON中是不允许的。{name:Tom,// 用户名age:18/* 成年了 */}解决方案先清注释再解析importjsonimportredefstrip_comments(s):# 去除 // 注释sre.sub(r//.*,,s)# 去除 /* */ 注释sre.sub(r/\*.*?\*/,,s,flagsre.DOTALL)returns raw { name: Tom, // 用户名 age: 18 } cleanstrip_comments(raw)resultjson.loads(clean)print(result)或者直接用demjson3一步到位importdemjson3 resultdemjson3.decode(raw)场景四JavaScript风格的特殊值{value:undefined,number:NaN,big:Infinity}这些在标准JSON中不存在但在JS生态中很常见。JS值JSON等价demjson3处理结果undefined无NoneNaN无nanfloatInfinity无inffloattrue/falsetrue/false正常解析importdemjson3 data{value: undefined, num: NaN, big: Infinity}resultdemjson3.decode(data)print(result)# {value: None, num: nan, big: inf}方案对比方案适用场景优点缺点json.loads标准JSON快、安全、内置只能处理标准JSONast.literal_evalPython风格字典安全、内置不识别null/true/falsedemjson3几乎所有非标准情况功能最全性能较慢依赖第三方正则替换json简单单引号/逗号场景轻量容易出错维护成本高实践建议能用标准JSON就用标准JSON——这是根治问题的方式数据来源可信 格式简单→ 用ast.literal_eval性能好且安全数据来源杂、格式乱→ 直接上demjson3别自己造轮子生产环境对性能敏感→ 先做数据清洗再用json.loads总结非标准JSON的本质是数据生产方和消费方对什么是合法JSON的定义不一致。Python生态的解决思路也很清晰轻量场景 →ast.literal_eval重度场景 →demjson3极致场景 → 自己写清洗逻辑选哪个取决于你的数据有多脏。