You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Opis JSON Schema验证PHP数据提示需匹配object类型报错排查

Opis JSON Schema校验关联数组报类型不匹配问题

问题复现

在PHP项目中使用Opis JSON Schema实现JSON数据校验时,会遇到传入符合字段规则的关联数组却被提示类型不匹配的问题,复现条件如下:

  • 编写的Schema文件user-data.schema.json内容如下:
{
  "$id": "https://www.example.com/user-data.schema.json",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "User Data",
  "type": "object",
  "required": [ "regIpAddress" ],
  "properties": {
    "regIpAddress": {
      "type": "string"
    }
  },
  "additionalProperties": true
}
  • 编写的校验逻辑代码如下:
$validator = new Validator();
$resolver = $validator->loader()->resolver();
$resolver->registerPrefix('https://www.example.com/', '/app/web/modules/custom/mymodule/schema');
$result = $validator->validate($json_array, 'https://www.example.com/user-data.schema.json');
if ($result->isValid()) {
  $encoded_preferences = json_encode($json_array);
  $this->set('myfield', json_encode($json_array));
} else {
  $error = $result->error();
  $formatter = new ErrorFormatter();

  // 打印辅助方法
  $print = function ($value) {
    return json_encode(
      $value,
      JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES
    );
  };
  $user_id = $this->id();
  $error_message = "User id: $user_id " . $print($formatter->formatOutput($error, "verbose"));
  $encoded_preferences = json_encode($json_array);
  throw new InvalidJsonException("JSON user data failed to validate! $error_message, $encoded_preferences");
  • 传入的待校验数据为PHP关联数组,内容如下:
[
   "regIpAddress" => "host.docker.internal",
   "emailVerifyCode" => "965",
]
  • 校验时返回如下错误:
{ 
  "keywordLocation": "#/type", 
  "instanceLocation": "#", 
  "error": "The data ({type}) must match the type: object", 
  "valid": false, 
  "absoluteKeywordLocation": "https://www.example.com/user-data.schema.json#/type" 
}
  • 临时处理方式:校验前对$json_array做一次json_encode再json_decode处理即可通过校验,代码如下:
$json_array = json_decode(json_encode($json_array));
$result = $validator->validate($json_array, 'https://www.example.com/user-data.schema.json');

问题根因

该问题的核心原因是Opis JSON Schema的类型校验严格对齐JSON类型规范:
*JSON标准中的object类型,在校验逻辑中仅匹配PHP的stdClass实例;PHP的关联数组本质为array类型,会被默认识别为JSON array类型,和Schema中声明的type: object规则不匹配,因此校验器直接抛出顶层类型错误,不会进入后续字段规则校验流程。
临时方案中json_encode拼接json_decode之所以能生效,是因为默认配置下json_decode不传第二个参数时,会将JSON对象解析为stdClass实例,类型符合校验要求后即可正常执行后续校验。

正确修复方案

json_encode+json_decode的处理方式存在不必要的序列化/反序列化开销,数据量较大时性能损耗明显,不推荐使用。正确处理方式非常简单,传入校验数据前将关联数组强转为stdClass对象即可,转换效率远高于编解码方案:

// 将PHP关联数组强转为stdClass对象,对齐JSON object类型要求
$validateData = (object)$json_array;
$result = $validator->validate($validateData, 'https://www.example.com/user-data.schema.json');

如果业务逻辑里必须保留数组格式处理数据,也可以仅在校验环节做一次对象转换,其余流程继续使用关联数组即可,不需要改动原有业务逻辑。

内容的提问来源于stack exchange,提问作者Patrick Kenny

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 02:03:25