php输出json中文乱码需同时设置json_encode($data, json_unescaped_unicode)和header('content-type: application/json; charset=utf-8'),并确保文件utf-8无bom、mysql连接为utf8mb4;json_encode()返回false时须用json_last_error_msg()排查,常见原因包括资源句柄、循环引用、非utf-8数据等。

PHP输出JSON时中文变空或乱码
直接用 json_encode() 处理含中文的数组,默认会把中文转成 \uXXXX 格式,前端拿到的是转义字符串,不是可读中文;更糟的是,如果没设对响应头,浏览器或客户端可能按 ISO-8859-1 解析,直接显示乱码。
- 必须加
JSON_UNESCAPED_UNICODE参数:json_encode($data, JSON_UNESCAPED_UNICODE) - 务必设置响应头:
header('Content-Type: application/json; charset=utf-8'),缺一不可 - 确保 PHP 文件本身是 UTF-8 编码(无 BOM),否则
json_encode()可能静默失败 - 如果数据来自 MySQL,确认连接字符集是
utf8mb4,并执行过SET NAMES utf8mb4
json_encode() 返回 false 却不报错
这是最常被忽略的坑——json_encode() 遇到无法序列化的值(比如资源句柄、含循环引用的对象、不可序列化的类实例)时,只返回 false,不抛异常,也不提示哪出错了。
- 先用
json_last_error()和json_last_error_msg()查原因,例如:var_dump(json_last_error_msg()) - 常见罪魁祸首:MySQL 查询结果未
fetch_all()就直接传给json_encode()(返回的是资源,不是数组) - 对象要可序列化,要么实现
JsonSerializable接口,要么确保所有属性可访问且不含资源 - 数值超限也会失败(如
INF、NAN),可用is_finite()预检
PHP接口返回JSON但前端收不到或解析失败
不是后端没输出,而是 HTTP 层或内容协商出了问题。尤其在调试时用 curl 或 Postman 看到空白响应,大概率是 header 或输出缓冲干扰了 JSON 流。
- 确认没有意外输出:开头不能有空格、BOM、
echo、print或 warning 日志(开启display_errors = Off生产环境) - 关闭输出缓冲干扰:
ob_end_clean()放在json_encode()前,避免缓存中残留 HTML 片段 - 不要用
exit()或die()终止,改用http_response_code(200)+exit($json),保证只输出 JSON 字符串 - 如果用了框架(如 Laravel、ThinkPHP),别手动
header(),优先走框架的响应构造器,避免 header 冲突
需要带状态码和统一结构的 JSON 接口
纯 json_encode() 只负责序列化,HTTP 状态码、业务字段(如 code、msg、data)得自己组织。硬编码容易漏字段、错状态,建议封装最小必要逻辑。
立即学习“PHP免费学习笔记(深入)”;
- 示例结构:
['code' => 0, 'msg' => 'ok', 'data' => $real_data],code为 0 表示成功 - 失败时用
http_response_code(400)或500,再返回对应code值,前端靠 HTTP 状态码 +code双重判断 - 避免在
data里塞原始数据库记录(含敏感字段),始终做显式白名单过滤 - 大数组慎用
JSON_PRETTY_PRINT,它会增加大量空格换行,浪费带宽且无缓存优势
真正卡住人的往往不是怎么写 json_encode(),而是它什么也不说——返回 false、没报错、没日志、前端只看到空响应。每次出问题,先查 json_last_error_msg(),再看响应头和输出缓冲,比重写逻辑快得多。











