json.loads()解析失败主因是响应非纯json,需先验状态码、查bom、检开头字符;深层字段用jsonpath-ng更稳;时间字符串须手动转datetime;大文件应选ijson流式解析。

json.loads() 解析失败:不是所有字符串都能直接喂给它
遇到 JSONDecodeError,八成是响应体根本不是纯 JSON——比如混了 HTML 注释、BOM 头、或者后端返回了 502 页面但你没检查状态码。别急着换库,先确认 response.text 开头是不是 { 或 [。
- 用
response.content[:100]看原始字节,比.text更可靠(尤其含中文或编码混乱时) - 如果开头是
b'\xef\xbb\xbf{',说明有 UTF-8 BOM,得先切掉:response.content.decode('utf-8-sig') - 后端返回 HTML 错误页却 content-type 写成
application/json?必须加if response.status_code == 200:再解析
嵌套太深,用 jsonpath-ng 比写四层 .get() 更稳
手写 data.get('a', {}).get('b', {}).get('c', {}).get('list', []) 不仅难读,还容易漏掉某层为 None 导致 AttributeError。真要查深层字段,jsonpath-ng 是更轻量的解法,比 jmespath 依赖少,也比正则靠谱。
- 安装:
pip install jsonpath-ng - 查所有用户邮箱:
jsonpath_ng.parse('$.users[*].contact.email').find(data) - 结果是对象列表,取值用
[match.value for match in matches],空结果返回空列表,不抛错 - 注意:
$是根,[*]才能遍历数组,写成[0]会漏数据
datetime 字符串没转,后续计算直接报错
JSON 里的时间永远是字符串,json.loads() 不会自动变 datetime 对象。如果你拿 data['created_at'] > '2024-01-01' 做比较,实际是字符串字典序,2023-12-31 会大于 2024-01-01。
- 简单场景用
datetime.fromisoformat()(Python 3.7+),支持'2024-03-15T14:30:00'和'2024-03-15T14:30:00+08:00' - 遇到
'2024/03/15 14:30:00'这种格式,老实用datetime.strptime(s, '%Y/%m/%d %H:%M:%S') - 千万别在
json.loads()的object_hook里全局转换时间字段——你没法预知哪些 key 叫created_at,哪些叫update_time,硬写反而埋雷
大 JSON 文件内存爆掉,别一次性 load
json.loads() 必须把整个字符串载入内存再解析,100MB 的 JSON 文件可能吃掉 300MB+ 内存。真要处理大文件,优先考虑流式解析。
- 小改动就能降内存:
json.load(open('big.json'))比json.loads(open('big.json').read())省一半内存(避免中间字符串拷贝) - 真正上 GB?用
ijson库:ijson.parse()返回生成器,按需取users.item.name这类路径,内存占用恒定在几 MB - 别信“用 ujson 就快”——它只加速解析,不解决内存问题;而且对非标准 JSON(如尾部逗号)更严格,容易翻车
复杂点在于:没有银弹。BOM 要手动切,时间要自己转,大文件得换库,嵌套深了得选查询语法——这些事都得你判断哪条路成本最低,而不是幻想一个函数全搞定。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











