Watch at Ease看见世界,读懂生活。

科技 · 实用指南

requests 报 JSONDecodeError char 0?解析前先证明响应字节

保存最终 URL、状态码、Content-Type、原始字节长度和安全前缀,再区分合法空响应、HTML/文本、已消费流与真正 JSON。

zh-CN diagram of the HTTP response evidence chain before JSON parsing
原创插画:解析前保存完整响应证据链。 Watch at Ease

“Expecting value: line 1 column 1 (char 0)” 只说明解析器在起点没有找到 JSON 值,并不证明引号、库或服务器一定有问题。

重试前固定同一次响应的请求、跳转、状态、媒体类型、字节长度和脱敏前缀,让证据指向真正的 HTTP 或流边界。

重试前冻结一次失败交换

记录同一次失败调用的方法、脱敏目标、status_code、最终 URL 和跳转历史;有条件时保存时间与关联 ID。

不要记录凭据、Cookie、Authorization 或无限正文;只保存选择后的头与短脱敏前缀。

选解析器前先测量字节

把 response.content 一次读入受限变量并记录长度;零字节说明根本没有 JSON 文档。

若使用 stream=True,要证明谁拥有读取权;iter_content、raw.read 或中间件可能已把流推进到末尾。

联合解释状态、跳转与 Content-Type

Requests 明确说明 204 或无效正文会让 json() 抛错;204 可能是合法结果,应按接口契约返回“无对象”。

检查最终 URL 和跳转;登录页、限流页、404 HTML 与 502 网关页常以“<”开头并在 char 0 失败。

区分 HTTP 失败和表示失败

是否先 raise_for_status 取决于 API 契约;有些错误状态返回 JSON,有些返回 HTML。

状态异常先修认证、端点、跳转、代理或上游;状态正常但正文类型不符,则保留样本并报告表示契约违约。

只解析一次并证明退出条件

确认契约允许 JSON 且字节非空后,才调用 response.json() 或 json.loads(body)。

用同一运行时和网络路径重放:状态符合预期、类型兼容、字节非零、解析成功且 schema 通过,才算结案。

zh-CN decision tree for empty, non-JSON and JSON response bodies
原创插画:按空、非 JSON 与 JSON 字节分支。 Watch at Ease