TP6接口JSON中文显示\uXXXX是默认行为,非乱码;真正导致解析失败或显示问号/方块的根源在于PHP文件编码(须UTF-8无BOM)、数据源编码(如MySQL需utf8mb4)及响应头缺失(application/json; charset=utf-8),三者必须同时满足。

json() 返回中文显示为 \uXXXX 形式不是乱码,是 PHP 默认行为;真正导致前端解析失败、浏览器显示问号或方块的“乱码”,根源在三处:PHP 文件编码、数据源编码、响应头缺失。必须逐层排查,不能只改一个地方。
确认 PHP 文件是否 UTF-8 无 BOM
这是最隐蔽也最致命的一环。哪怕 app/controller/User.php 开头多了一个不可见的 BOM(EF BB BF),就会在 json() 前输出三个字节,导致 JSON 格式损坏,浏览器报 Unexpected token in JSON at position 0。
- 用 VS Code 或 PhpStorm 打开所有 PHP 文件(尤其
app/、config/、route/目录),右下角检查编码格式,手动转为「UTF-8 without BOM」 - 禁用任何前置
echo、var_dump(),也避免未定义数组键触发 Notice(如$data['name']但$data不含该键) - 用命令行快速检测:
file -i *.php查看是否含with BOM字样
让 json() 输出可读中文:启用 JSON_UNESCAPED_UNICODE
默认 json($data) 会把中文转成 \u5f20\u4e09,虽不影响解析,但调试困难。关键不是“修复乱码”,而是控制编码行为。
- TP6.1+:直接在
config/app.php中添加配置:'json_encode' => [JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES], - TP6.0:不支持该配置,只能在控制器中手动写:
return response(json_encode($data, JSON_UNESCAPED_UNICODE))->header('Content-Type', 'application/json; charset=utf-8'); - 切勿混用:
json(json_encode($data))会导致双重编码,返回无效 JSON
检查数据源是否真为 UTF-8
即使开了 JSON_UNESCAPED_UNICODE,如果数据库查出来就是乱码(比如显示为 “寮笁”),那 JSON 里仍是错的。问题不在 JSON 编码,而在源头。
- MySQL 连接必须设死
'charset' => 'utf8mb4',不能写utf8或留空 - TP6 不自动执行
SET NAMES utf8mb4,建议在app/common.php加:Db::connect()->execute('SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci'); - 若 POST 来自老旧 GBK 表单(如 IE),需在中间件或
app\common\boot\AppService.php的boot()中处理原始输入:$raw = file_get_contents('php://input');<br>$utf8 = mb_convert_encoding($raw, 'UTF-8', 'GBK');
强制设置响应头并避开输出污染
仅靠前端发 Accept: application/json 并不能保证 TP6 返回 JSON——框架可能因请求类型误走 HTML 渲染流程。
立即学习“PHP免费学习笔记(深入)”;
- 统一用
return json($data, $code),别依赖“发 JSON 请求就自动回 JSON” - Postman 测试时,
Content-Type写application/json(不含; charset=utf-8),某些 TP6.0.x 版本会因此跳过 JSON 解析 - 用
json_last_error_msg()检查失败原因,常见是Malformed UTF-8 characters,说明某处字符串非 UTF-8
file -i *.php 和 SHOW VARIABLES LIKE 'character%';,比反复改 json_encode 参数快得多。



















