Yii2处理JSON请求需先配置JsonParser解析器,再通过模型规则或手动解析进行结构化验证。配置parsers后可用bodyParams获取数据;推荐用继承Model的验证类绑定并校验;动态场景可手动解析rawBody后自定义校验逻辑。

Yii2 接收 JSON 请求时,参数验证不能只靠 $request->post() 或 getBodyParam() 拿到数据就直接校验——因为 JSON 数据结构灵活、字段嵌套常见、空值/类型错位频发,必须在解析后、业务逻辑前做统一清洗和强约束校验。
确保 JSON 能被自动解析
这是前提。若没配置好解析器,连原始数据都拿不全,验证无从谈起:
- 在
config/web.php的'components' => ['request' => [...]]中加入:
'parsers' => [
'application/json' => 'yii\web\JsonParser',
],
```
- 配置后,
$request->post('field')和$request->post()就能正常读取 JSON 字段(如{"name":"张三","age":25}) - 注意:该配置对
application/json;charset=UTF-8同样生效,无需额外处理 charset
用模型规则做结构化验证(推荐)
把 JSON 数据绑定到一个继承 yii\base\Model 的验证类,复用 Yii2 内置的规则引擎,清晰且可复用:
- 定义验证模型,例如
LoginForm:
class LoginForm extends \yii\base\Model
{
public $username;
public $password;
public $rememberMe = true;
public function rules()
{
return [
[['username', 'password'], 'required'],
['username', 'string', 'min' => 2, 'max' => 32],
['password', 'string', 'min' => 6],
['rememberMe', 'boolean'],
];
}
}
```
- 在控制器中使用:
$model = new LoginForm();
$model->load(Yii::$app->request->bodyParams, ''); // 注意第二个参数为空字符串
if (!$model->validate()) {
throw new \yii\web\BadRequestHttpException(
json_encode($model->errors, JSON_UNESCAPED_UNICODE)
);
}
// 此时 $model->username 等字段已安全可用
```
手动解析 + 自定义校验逻辑(适合动态或非结构化场景)
当 JSON 结构不确定(如 Webhook 回调、第三方推送),或需做跨字段逻辑判断(如“start_time 必须早于 end_time”),可跳过模型,直接操作原始数组并手动验证:
- 先获取并校验 JSON 是否合法:
$raw = Yii::$app->request->getRawBody();
if (empty($raw)) {
throw new \yii\web\BadRequestHttpException('Empty request body');
$data = json_decode($raw, true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new \yii\web\BadRequestHttpException('Invalid JSON format');
}
```
- 再逐项检查关键字段:
if (!isset($data['event']) || !is_string($data['event'])) {
throw new \yii\web\BadRequestHttpException('"event" must be a non-empty string');
}
if (!isset($data['payload']) || !is_array($data['payload'])) {
throw new \yii\web\BadRequestHttpException('"payload" must be an object');
}
// 可继续校验 payload 内部字段…
```
统一错误响应格式(让前端好解析)
无论哪种验证方式失败,都应返回标准 JSON 错误结构,避免前端反复适配不同格式:
- 建议响应体统一为:
{"success":false,"data":{"code":400,"message":"xxx"}} - 可在基类控制器中封装一个方法:
protected function fail($message, $code = 400)
{
Yii::$app->response->statusCode = $code;
return ['success' => false, 'data' => ['code' => $code, 'message' => $message]];
}
// 使用:
// return $this->fail('用户名不能为空');
```
- 配合全局
beforeSend处理,还能自动将异常也转为此格式(参考知识库中 API 统一输出部分)


















