PHP输出JSON需先调用header('Content-Type: application/json; charset=utf-8'),确保无BOM、空格等前置输出;json_encode()应使用JSON_UNESCAPED_UNICODE和JSON_UNESCAPED_SLASHES参数,并检查返回值是否为false。

PHP 输出 JSON 时 header() 必须先调用
浏览器或前端 JS 要正确解析 PHP 返回的 JSON,header('Content-Type: application/json; charset=utf-8') 必须在任何输出(包括空格、BOM、echo、print)之前执行。一旦有额外输出,JSON 就会变成非法格式,前端 JSON.parse() 报错 SyntaxError: Unexpected token。
常见踩坑点:
- PHP 文件开头有 UTF-8 BOM(尤其 Windows 编辑器保存时默认带),导致隐式输出
-
require或include的文件末尾有多余换行或空格 - 调用
var_dump()、error_log()后忘记注释或删除
建议统一用 ob_start() 开启输出缓冲,最后用 ob_end_clean() 清掉意外内容,再输出 JSON —— 但这只是补救,根源还是清理源码。
json_encode() 的参数不能忽略
json_encode() 默认不处理中文字符(会转成 \uXXXX),也不兼容某些特殊数据类型。实际开发中至少要加两个参数:
立即学习“PHP免费学习笔记(深入)”;
-
JSON_UNESCAPED_UNICODE:保留中文原样,避免前端看到一堆\u676e -
JSON_UNESCAPED_SLASHES:防止 URL 中的/被转义成\/,影响前端路由或 API 使用 - 如果数据含资源(如 MySQL result resource)、对象未实现
JsonSerializable,json_encode()会返回false—— 务必用if ($json === false)检查并记录json_last_error_msg()
示例写法:
$data = ['name' => '张三', 'url' => 'https://example.com/api'];
$json = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
if ($json === false) {
http_response_code(500);
echo json_encode(['error' => json_last_error_msg()], JSON_UNESCAPED_UNICODE);
exit;
}
header('Content-Type: application/json; charset=utf-8');
echo $json;
GET/POST 请求下 JSON 输出逻辑要隔离
动态网站常混用 HTML 渲染和 API 接口,不能让一个 PHP 脚本既输出网页又输出 JSON。否则容易因模板引擎(如 Smarty、Twig)或框架视图层干扰 JSON 格式。
推荐做法:
- API 接口单独放在
/api/目录下(如/api/user.php),不引入任何视图层 - 用
$_SERVER['REQUEST_METHOD']明确判断请求方式,拒绝非预期方法(如只允许 POST 的接口收到 GET 就直接http_response_code(405)) - 若必须共存(如 WordPress 主题里加 AJAX endpoint),用
wp_die()或die()在输出 JSON 后立即终止,防止后续代码追加输出
调试时别依赖浏览器直接访问 JSON 接口
用浏览器地址栏打开 http://localhost/api/data.php 看到“乱码”或空白,不等于 JSON 出错 —— 很可能是浏览器没渲染纯文本,或响应头缺失导致显示异常。
真正有效的验证方式:
- 用
curl -I http://localhost/api/data.php查看响应头是否含Content-Type: application/json - 用
curl http://localhost/api/data.php | python3 -m json.tool格式化并校验 JSON 合法性 - Chrome DevTools 的 Network → Preview 标签页比 Response 更直观,能自动高亮语法错误
另外,json_encode() 对 NaN、Infinity、资源、闭包等值直接返回 null 或 false,这类数据必须提前过滤或转换,否则前端拿到的是静默损坏的数据。











