yii2中验证json需自定义逻辑:1.用json_decode+json_last_error校验合法性;2.进一步检查内部结构如字段类型;3.区分表单与api场景处理raw body;4.可封装为复用的jsonvalidator类。

在 Yii2 中验证 JSON 格式参数,核心是先确保字段内容是合法 JSON 字符串,再按需校验其内部结构。不能直接用 json 规则(Yii2 本身无内置 json 验证器),需自定义验证逻辑。
1. 自定义验证方法:检查是否为有效 JSON 字符串
在模型中添加一个验证方法,使用 json_decode($value, true) 判断是否解析成功,并排除 null(因空字符串、"null" 等也会返回 null):
注意:需同时检查 json_last_error() === JSON_ERROR_NONE,避免依赖返回值是否为 null(如 "null" 是合法 JSON,但解码后也是 null)。
- 在模型的
rules()中引用该方法,例如:['config', 'validateJsonString'] - 实现方法如下:
public function validateJsonString($attribute, $params)
{
$value = $this->$attribute;
if (!is_string($value) || $value === '') {
$this->addError($attribute, '必须为非空字符串');
return;
}
$decoded = json_decode($value, true);
if (json_last_error() !== JSON_ERROR_NONE) {
$this->addError($attribute, '不是合法的 JSON 格式');
return;
}
// 可选:进一步拒绝 "null" 字符串(即 JSON 文本就是 "null")
// if ($decoded === null && $value !== 'null') {
// $this->addError($attribute, 'JSON 解析结果不能为 null');
// }
}
2. 进阶校验:验证 JSON 内容结构(如必需字段、类型)
仅校验“是 JSON”还不够,常需确保它包含特定 key、对应值为指定类型(如 status 是整数、items 是数组等)。可在同一验证方法中扩展,或拆分为独立方法(如 validateJsonStructure):
Miller (mlr) 是一个命令行工具,用于查询、整形和重新格式化名称索引数据,如 CSV、TSV、JSON 和 JSON Lines。它将 awk、sed、cut、join 和 sort 的功能整合到一个专为结构化数据处理而构建的单一工具中。
- 先通过
json_decode得到 PHP 数组/对象 - 用
isset()、is_array()、is_int()等判断结构 - 示例:要求 JSON 必须有
name(字符串)和count(正整数):
public function validateJsonStructure($attribute, $params)
{
$value = $this->$attribute;
$data = json_decode($value, true);
if (json_last_error() !== JSON_ERROR_NONE) {
return; // 前置校验应已拦截,此处可跳过或只 warn
}
if (!isset($data['name']) || !is_string($data['name']) || trim($data['name']) === '') {
$this->addError($attribute, 'JSON 中缺少有效的 "name" 字段');
}
if (!isset($data['count']) || !is_int($data['count']) || $data['count'] addError($attribute, 'JSON 中 "count" 必须是非负整数');
}
}
3. 配合表单提交与 API 场景的注意事项
前端传 JSON 时常见两种方式,后端处理逻辑略有不同:
-
作为普通表单字段值(如
<input name="config">填{"a":1}):直接走上述验证即可 -
作为 raw body(如 POST JSON API):需在控制器中手动读取并赋值,例如:
$rawBody = file_get_contents('php://input');<br>$model->config = $rawBody;
再调用$model->validate() - 若用
yii\rest\ActiveController,默认会自动解析 JSON body 到$model->load(),但前提是 Content-Type 为application/json且数据结构匹配;否则仍需手动处理
4. 封装成独立验证器(复用性更高)
若多个模型都要校验 JSON,建议封装为自定义验证器类,继承 yii\validators\Validator:
- 创建
common/validators/JsonValidator.php - 重写
validateAttribute(),内含同上的解析 + 错误设置逻辑 - 支持配置选项,如
'strict' => true(拒绝null/false/0等 falsy 值)、'structure' => ['name' => 'string'] - 规则写法变为:
['config', JsonValidator::class]
这样既保持模型轻量,又便于统一维护和测试。










