根本原因是UTF-8编码链路被破坏;需确保PHP文件为UTF-8无BOM格式、数据源统一UTF-8、启用JSON_UNESCAPED_UNICODE选项,并检查json_encode是否因非法字符返回false。

ThinkPHP 接口返回 JSON 出现中文乱码,根本原因不是“没加编码”,而是UTF-8 编码链路在某个环节被破坏。TP6 的 json() 方法默认已设 Content-Type: application/json; charset=utf-8,但若数据源、文件本身或运行环境不匹配 UTF-8,依然会输出 \u4f60\u597d 或解析失败。
确保所有 PHP 文件是 UTF-8 无 BOM 格式
BOM(EF BB BF)是隐藏字节,出现在文件开头时会被当成实际输出,导致 json() 前已有内容——这是最常见却最容易被忽略的乱码源头。
- 用 VS Code、Sublime 或 PHPStorm 打开每个控制器、配置、路由、中间件文件,检查右下角编码显示是否为 UTF-8(无 BOM);不是就点击切换并保存
- 特别注意
config/目录下的 PHP 配置文件,常因复制粘贴带入 BOM - Windows 记事本保存的文件几乎 100% 带 BOM 或 ANSI 编码,务必弃用
让 json() 正确处理中文字符
TP6 的 json($data) 默认会对中文做 Unicode 转义("\u60a8\u597d"),这不是错误,但前端看到的是转义串而非原文。要显示原生中文,必须启用 JSON_UNESCAPED_UNICODE:
- 正确写法:
return json($data, JSON_UNESCAPED_UNICODE); - 如需紧凑格式(无换行缩进),可叠加:
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES - 不要写
echo json_encode(...)—— 绕过框架响应机制,容易触发 headers already sent 错误
验证并统一数据源头的编码
即使 PHP 文件和响应头都对了,如果从数据库、文件、POST 请求中读取的数据本身不是 UTF-8,json_encode() 仍会返回 null 或乱码。
立即学习“PHP免费学习笔记(深入)”;
- MySQL 连接必须用
utf8mb4:PDO DSN 加;charset=utf8mb4,MySQLi 调用$mysqli->set_charset('utf8mb4') - 读取外部 JSON 文件时,先检测编码:
$str = file_get_contents('data.json'); $enc = mb_detect_encoding($str, ['UTF-8', 'GBK'], true); $str = mb_convert_encoding($str, 'UTF-8', $enc); - 接收 POST 表单或 API 请求体时,确认前端发送的 Content-Type 是
application/json,且 JSON 字符串本身是合法 UTF-8(避免编辑器保存时转成 GBK)
检查 json_encode 是否静默失败
json_encode() 对非法 UTF-8 字节、资源类型、闭包等直接返回 false,不报错也不提示。接口返回空或 null 很可能源于此。
- 调试时加判断:
$json = json_encode($data, JSON_UNESCAPED_UNICODE); if ($json === false) { error_log('JSON encode failed: ' . json_last_error_msg()); } - PHP 7.2+ 可用
JSON_INVALID_UTF8_SUBSTITUTE替换非法字节:json_encode($data, JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE) - 避免把 DateTime、Resource、Closure 等不可序列化对象直接塞进
$data



















