php输出json时必须设置content-type为application/json且声明charset=utf-8,否则python的response.json()会因解析非json内容而抛出jsondecodeerror。

PHP 输出 JSON 时必须设置 Content-Type
Python 的 requests.get() 或 urllib.request 默认把响应体当字符串处理,不自动解析 JSON。如果 PHP 端没设 Content-Type: application/json,Python 收到的仍是原始字节流,response.json() 会抛 JSONDecodeError。
正确做法是 PHP 中先调用 header(),再输出 JSON:
header('Content-Type: application/json; charset=utf-8');
echo json_encode(['status' => 'ok', 'data' => [1, 2, 3]]);
- 漏掉
header()是跨语言调试中最常见的“Python 解析失败”原因 -
charset=utf-8必须显式声明,否则中文在 Python 侧可能乱码 - 不要在
json_encode()前有任何输出(包括空格、BOM、echo ''),否则 HTTP 头已发送,header()会警告并失效
PHP json_encode() 的常见陷阱与 Python 兼容性
json_encode() 默认不处理资源、闭包、不可序列化对象,遇到会返回 false,最终输出空字符串或 "null",Python 侧收到非法 JSON。
关键检查点:
立即学习“PHP免费学习笔记(深入)”;
- 确保数据中不含
resource(如 MySQLi 连接句柄)、DOMDocument等原生对象 - 含中文时,确认 PHP 文件本身保存为 UTF-8 无 BOM 格式;否则
json_encode()可能静默失败 - 若需保留数字精度(如金融金额),避免用 float 类型传入;PHP 浮点数经
json_encode()后在 Python 侧可能变成近似值(例如123.45变成123.45000000000002),建议统一用字符串传输 - 使用
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES提升可读性,对 Python 解析无影响但便于调试
Python 接收时如何安全解析 PHP 返回的 JSON
不能直接调用 response.json() —— 它在状态码非 2xx 时仍会尝试解析,而 PHP 错误页(如 500)返回的是 HTML,必然报错。
推荐写法:
import requests
r = requests.get('https://api.example.com/data.php')
if r.status_code == 200:
try:
data = r.json()
except ValueError as e:
print('JSON 解析失败:', e)
print('响应内容:', r.text[:200])
else:
print('HTTP 错误:', r.status_code)
- 始终先检查
r.status_code,再调用.json() - 捕获
ValueError(Python 3.5+ 中json.JSONDecodeError是其子类),而不是JSONDecodeError单独捕获,兼容性更好 - 打印
r.text[:200]能快速发现 PHP 是否返回了错误信息(如Parse error:)而非 JSON
调试时怎么快速定位是 PHP 还是 Python 出问题
最有效方式:绕过 Python,用命令行直接请求 PHP 接口,看原始响应是否合法 JSON。
执行:
curl -i https://api.example.com/data.php
- 观察第一行是否为
HTTP/1.1 200 OK - 查看
Content-Type响应头是否为application/json - 复制响应体粘贴到 jsonlint.com 验证格式
- 如果 curl 返回的是 PHP 错误(如
Warning: ...)或 HTML,则问题 100% 在 PHP 端未正确处理异常或输出
跨语言 JSON 交互真正难的不是语法,而是 HTTP 层细节和错误传播被掩盖——一旦 PHP 报错但没关掉 display_errors,它就把错误信息混在 JSON 前面输出,Python 拿到的就是“开头是 HTML、中间是 JSON”的脏数据,这种问题只能靠 curl + 查看原始响应体来揪出。











