ThinkPHP 6 的 json() 默认转义中文是因未启用 JSON_UNESCAPED_UNICODE,可通过 config/app.php 全局配置、手动调用 json_encode() 或中间件统一处理解决,推荐 TP6.1+ 使用全局配置方式。

ThinkPHP 6 的 json() 默认会转义中文
默认情况下,ThinkPHP 6 的 json() 方法(包括 return json($data))底层调用的是 PHP 原生的 json_encode(),且未传入 JSON_UNESCAPED_UNICODE 标志,所以中文会被编码成 \uXXXX 形式。这不是 bug,是默认行为,但接口返回带转义的中文对前端调试、日志查看都不友好。
常见错误现象:{"name":"\u5f20\u4e09"} 而不是 {"name":"张三"};Postman 或浏览器直接打开接口看到一堆 \u 编码。
- 使用场景:API 接口开发、前后端分离项目、需要人工可读 JSON 的调试环境
- 注意:仅影响输出内容显示,不影响 JSON 解析正确性 —— 浏览器和大多数语言的 JSON 解析器都能正常处理 \u 编码
- 性能影响几乎为零,
JSON_UNESCAPED_UNICODE是 PHP 内置标志,无额外开销
全局配置 json_encode 选项(TP6.1+)
ThinkPHP 6.1 起支持在 config/app.php 中配置 JSON 编码选项,这是最干净、一劳永逸的方式。
修改 config/app.php,找到或新增 'json_encode' => [] 配置项:
立即学习“PHP免费学习笔记(深入)”;
'json_encode' => [
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES,
],
这样所有 json()、response()->json()、以及框架内部自动 JSON 化(如异常响应)都会带上这两个标志。
-
JSON_UNESCAPED_UNICODE:关键,让中文不被转义 -
JSON_UNESCAPED_SLASHES:顺手加上,避免/被转成\/,更简洁 - 旧版本 TP6.0 不支持该配置,需手动封装或中间件处理
手动调用 json_encode() 替代 json()(兼容所有 TP6)
如果不能升级或需临时控制某一个接口,直接绕过框架封装,自己调用 json_encode() 并设置响应头即可。
示例(控制器中):
$data = ['name' => '李四', 'msg' => '操作成功'];
return response(json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES))
->header('Content-Type', 'application/json; charset=utf-8');
- 必须显式设置
Content-Type,否则可能被识别为text/html - 不要混用:避免写成
json(json_encode(...)),那会二次编码导致乱码 - 注意
json_encode()返回的是字符串,不是数组,别误传给其他需要数组的地方
中间件统一处理 JSON 响应(适合老项目或细粒度控制)
如果你的项目已有大量 return json(...) 调用,又不想逐个改,可以写一个响应中间件,在输出前拦截并重编码。
创建中间件(如 app/middleware/JsonUnescape.php),核心逻辑:
public function handle($request, \Closure $next)
{
$response = $next($request);
if ($response instanceof \think\Response
&& $response->getHeader('content-type') === 'application/json; charset=utf-8')
{
$content = $response->getContent();
$data = json_decode($content, true);
if (json_last_error() === JSON_ERROR_NONE && is_array($data)) {
$newContent = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
$response->content($newContent);
}
}
return $response;
}
- 只对明确标记为 JSON 的响应生效,避免误处理 HTML 或下载响应
- 依赖
json_decode→json_encode两次,有轻微性能损耗,但对大多数 API 场景可忽略 - 容易踩的坑:若原始响应已压缩(如 Gzip),中间件里直接改 content 会导致解压失败;确保该中间件在压缩中间件之前执行
真正要注意的其实是边界情况:比如接口返回了非 UTF-8 编码的字符串(如 GBK)、或者数据里混入了不可见控制字符,这时候加不加 JSON_UNESCAPED_UNICODE 都会出错 —— 编码一致性比转义与否更优先。










