python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Python解析非标准JSON

Python解析非标准JSON的踩坑记录和解决方案

作者:detayun

JSON是Web开发中最常用的数据交换格式,本文整理了几种常见的非标准JSON场景,以及对应的解决方案,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下

前言

JSON是Web开发中最常用的数据交换格式,但现实世界从来不按规范来。你可能遇到过这些情况:

Python自带的json.loads()遇到这些会直接报错。本文整理了几种常见的非标准JSON场景,以及对应的解决方案。

场景一:单引号 + 末尾逗号

这是最常见的"脏数据",通常来自手写配置或某些API的日志。

import json

data = "{'name': 'Tom', 'age': 18,}"  # 单引号 + 末尾逗号
# json.loads(data)  # 报错:JSONDecodeError

解决方案1:用ast.literal_eval(推荐)

import ast

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

ast.literal_eval可以安全地解析Python字面量,包括单引号字符串、末尾逗号、True/False/None等。

注意:它只能解析Python语法能识别的值,不能处理真正的JSON扩展。

解决方案2:先替换再解析

import json
import re

def fix_json(s):
    # 单引号 → 双引号(注意避免替换字符串内部的引号)
    s = re.sub(r"(?<!\\)'", '"', s)
    # 去除末尾逗号
    s = re.sub(r',\s*([\]}])', r'\1', s)
    return json.loads(s)

data = "{'name': 'Tom', 'age': 18,}"
result = fix_json(data)
print(result)

这种方式更灵活,但正则替换有边界风险,复杂场景容易漏。

场景二:键名未加引号

data = '{name: "Tom", age: 18}'  # 键名没引号,不是合法JSON

解决方案:用demjson3库

pip install demjson3
import demjson3

data = '{name: "Tom", age: 18}'
result = demjson3.decode(data)
print(result)  # {'name': 'Tom', 'age': 18}

demjson3是目前处理非标准JSON最强的第三方库,支持:

场景三:包含注释的JSON

某些配置文件会在JSON里加注释,这在标准JSON中是不允许的。

{
  "name": "Tom",  // 用户名
  "age": 18       /* 成年了 */
}

解决方案:先清注释,再解析

import json
import re

def strip_comments(s):
    # 去除 // 注释
    s = re.sub(r'//.*', '', s)
    # 去除 /* */ 注释
    s = re.sub(r'/\*.*?\*/', '', s, flags=re.DOTALL)
    return s

raw = '''
{
  "name": "Tom",  // 用户名
  "age": 18
}
'''
clean = strip_comments(raw)
result = json.loads(clean)
print(result)

或者直接用demjson3一步到位:

import demjson3
result = demjson3.decode(raw)

场景四:JavaScript风格的特殊值

{
  "value": undefined,
  "number": NaN,
  "big": Infinity
}

这些在标准JSON中不存在,但在JS生态中很常见。

JS值JSON等价demjson3处理结果
undefinedNone
NaNnan(float)
Infinityinf(float)
true/falsetrue/false正常解析
import demjson3
data = '{value: undefined, num: NaN, big: Infinity}'
result = demjson3.decode(data)
print(result)
# {'value': None, 'num': nan, 'big': inf}

方案对比

方案适用场景优点缺点
json.loads标准JSON快、安全、内置只能处理标准JSON
ast.literal_evalPython风格字典安全、内置不识别null/true/false
demjson3几乎所有非标准情况功能最全性能较慢,依赖第三方
正则替换+json简单单引号/逗号场景轻量容易出错,维护成本高

实践建议

  1. 能用标准JSON就用标准JSON——这是根治问题的方式
  2. 数据来源可信 + 格式简单 → 用ast.literal_eval,性能好且安全
  3. 数据来源杂、格式乱 → 直接上demjson3,别自己造轮子
  4. 生产环境对性能敏感 → 先做数据清洗,再用json.loads

知识扩展

在 Python 中解析非标准 JSON 数据,常见的情况包括:

处理这类数据不能直接用标准库 json,需要借助第三方库或手动预处理。

1.推荐方案:使用 json5 库(最标准、最全面)

json5 是 JSON5 格式的官方 Python 实现,JSON5 是 JSON 的超集,支持上述所有非标准特性。

pip install json5
import json5
data_str = """
{
  // 这是注释
  name: 'Alice',   // 键名无引号,字符串单引号
  age: 30,
  tags: ['dev', 'test',],  // 尾随逗号
}
"""
obj = json5.loads(data_str)
print(obj)  # {'name': 'Alice', 'age': 30, 'tags': ['dev', 'test']}

也可以从文件读取:

with open('data.json5', 'r', encoding='utf-8') as f:
    obj = json5.load(f)

2.备选方案:demjson(老牌,但维护较少)

demjson 也能处理许多非标准情况,但更新不活跃,且依赖较多。

pip install demjson
import demjson
data = "{name: 'Bob', age: 25,}"
obj = demjson.decode(data)
print(obj)

3.手动预处理(适合简单情况)

如果只有单引号问题,可以用正则或字符串替换:

import json
data = "{'name': 'John', 'age': 30}"   # 单引号
# 简单替换:将外层的单引号替换为双引号
# 注意:仅适用于字符串值不包含引号的情况,否则有风险
data_clean = data.replace("'", '"')
obj = json.loads(data_clean)
print(obj)

缺点:若字符串内容本身就含有单引号或双引号,会破坏结构。

4.使用 ast.literal_eval()(仅限 Python 字面量)

如果数据格式严格符合 Python 字面量(单引号、无键名引号等),可以用 ast.literal_eval,但不能解析 truefalsenull(Python 是 TrueFalseNone)。

import ast
data = "{name: 'Alice', age: 30}"
obj = ast.literal_eval(data)   # 返回 dict
print(obj)  # {'name': 'Alice', 'age': 30}

局限性:布尔值和 null 会报错,需要手动替换。

总结推荐

下面是使用 json5 的完整示例:

import json5
# 示例非标准 JSON
non_standard = """
{
  // 这是一条注释
  "name": "Mike",
  "age": 28,
  "address": {
    city: 'New York',
    zip: 10001,
  },
}
"""
parsed = json5.loads(non_standard)
print(parsed['address']['city'])  # New York

如果你需要处理大量类似数据,建议先统一转换成标准 JSON 格式保存,再使用原生 json 解析提高性能。

总结

非标准JSON的本质是:数据生产方和消费方对"什么是合法JSON"的定义不一致

Python生态的解决思路也很清晰:

选哪个,取决于你的数据有多"脏"。

到此这篇关于Python解析非标准JSON的踩坑记录和解决方案的文章就介绍到这了,更多相关Python解析非标准JSON内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文