直接替换 think\response\Json 类的 output() 方法即可统一 JSON 输出结构,因 json() 工厂方法最终调用该方法序列化数据;重写 __construct() 或 send() 会破坏状态码、Header 和 Content-Type 的自动管理,导致响应异常。

直接替换 think\response\Json 类就能接管所有 json() 调用的输出结构,但必须只重写 output($data) 方法,其他逻辑交给父类——否则会破坏框架对状态码、Header、Content-Type 的自动管理。
为什么不能继承后重写整个构造或 send()?
ThinkPHP 的 json() 工厂方法返回的是 think\Response 实例,最终由 think\response\Json 的 output() 决定怎么序列化数据。如果你重写了 __construct() 或 send(),会导致:
- 状态码(
$this->code)无法被正确写入响应头 -
Content-Type: application/json可能丢失或重复设置 - 中间件链中其他组件(如 CORS、压缩)收不到原始
Response对象,行为异常
怎么安全替换 output() 并保持标准结构?
在 app/common/Response/Json.php 中新建类:
namespace app\common\Response;
use think\Response;
class Json extends \think\response\Json
{
protected function output($data): string
{
// 提取原始 code 和 message,避免硬编码
$code = $this->code ?? 0;
$message = $this->message ?? ($code === 0 ? 'success' : 'error');
// 标准封装,data 字段只放业务数据
$result = [
'code' => $code,
'msg' => $message,
'data' => $data,
];
// 复用父类 json_encode 行为(已受 config/app.php 中 json_encode 配置影响)
return parent::output($result);
}
}
然后在 config/app.php 中指定:
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
立即学习“PHP免费学习笔记(深入)”;
'response' => [
'json' => \app\common\Response\Json::class,
],
这样所有 return json($data)、response()->json($data) 都会走你重写的 output(),且不干扰异常响应、验证失败等其他路径。
常见踩坑点:code/message 来源混乱
很多人直接在 output() 里写死 'code' => 0,结果控制器里调用 json($data, 400) 时 code 还是 0。正确做法是:
- 始终读取
$this->code和$this->message,它们由json()工厂方法或Response::code()设置 - 不要在
output()里 new 一个新 Response 或调用json_encode()后再包一层——这会绕过父类的 header 注入逻辑 - 如果需要兼容旧接口字段名(比如
status而非code),改$result数组键名即可,别动父类行为
注意:它不覆盖异常、验证失败、中间件返回的 JSON
这个替换只生效于显式调用 json() 的场景。验证失败(ValidateException)、未捕获异常、success()/error() Trait 方法,仍走各自响应通道。真要全局统一,得配合 Response::setSendCallback() 中间件兜底——那才是临界点控制,不是类替换能解决的。


















