yii2需显式设置response->format为json格式才能正确返回json响应,否则默认为text/html;应在action开头设置或通过beforeaction统一处理,并配置jsonresponseformatter支持中文及避免循环引用。

Yii2 默认不自动把数组响应转成 JSON,哪怕你 return ['msg' => 'ok'],响应头仍是 text/html,前端 fetch 或 axios 会解析失败。AJAX 请求要稳定返回 JSON,关键不是“猜请求类型”,而是主动控制 response->format 并确保它在序列化前生效。
在控制器 action 中显式设置 format
最直接、最可控的方式:在需要返回 JSON 的 action 开头就设格式,再 return 数组。
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;- 之后直接
return ['code' => 200, 'message' => '成功', 'data' => $result]; - 框架会自动调用
json_encode(),设置Content-Type: application/json,并带上正确 HTTP 状态码 - 切记不要自己
echo json_encode(...)或die(),否则绕过 Yii 响应生命周期,状态码、头信息全失效
统一处理所有 AJAX 请求(推荐)
避免每个 action 都写一遍 set format,可在控制器基类的 beforeAction() 中集中判断:
- 检查是否为 AJAX 请求:
Yii::$app->request->isAjax - 或检查 Content-Type 是否含
application/json:strpos(Yii::$app->request->getContentType(), 'application/json') !== false - 满足任一条件,立即执行
Yii::$app->response->format = Response::FORMAT_JSON - 这样表单提交、API 调用、前后端分离项目都能一致走 JSON 流程
让错误也返回 JSON(包括 4xx/5xx)
默认 ErrorHandler 只在特定条件下(如 YII_DEBUG=false 且 Accept 头匹配)才返回 JSON,实际 API 场景中不可靠。
- 在入口文件
web/index.php的(new Application($config))->run();前加事件监听: Yii::$app->on(Application::EVENT_BEFORE_REQUEST, function ($e) { if (Yii::$app->request->isAjax || strpos(Yii::$app->request->getContentType(), 'application/json') !== false) { Yii::$app->response->format = Response::FORMAT_JSON; } });- 同时配置
errorHandler组件,指定'errorAction' => 'site/error' - 确保
SiteController::actionError()中也设了 format 并 return 数组,否则 500 错误仍可能返回 HTML 页面
中文与特殊数据的安全输出
默认 JsonResponseFormatter 会对中文转义(\u4f60\u597d),且遇到 DateTime、Resource 或循环引用会静默失败,返回空响应。
- 在
config/web.php的components['response']中自定义 formatter: 'formatters' => [ Response::FORMAT_JSON => [ 'class' => 'yii\web\JsonResponseFormatter', 'encodeOptions' => JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES, ], ]- 对模型时间字段等,建议提前转换为字符串:
'created_at' => $model->created_at? $model->created_at->format('Y-m-d H:i:s') : null - 避免直接传对象或资源句柄到 response data 中











