PHP中json_decode转对象数组最直接的方法是json_decode($json, true),第二个参数true关键,否则返回stdClass对象导致数组语法报错;注意JSON合法性、UTF-8编码、循环引用及不可序列化类型问题。

PHP中用 json_decode 转对象数组最直接
如果原始数据是 JSON 字符串(比如 API 返回的),直接用 json_decode($json, true) 就能一步到位转成多维关联数组。第二个参数设为 true 是关键,否则默认返回 stdClass 对象。
常见错误是漏掉这个 true,结果得到一堆嵌套的 stdClass,后续用 $arr['key'] 会报错——因为对象得用 ->key 访问。
- 只对合法 JSON 字符串有效;含 PHP 对象或资源的变量不能这么转
- 注意字符编码,UTF-8 外的编码可能导致
null返回(可用json_last_error()检查) - 深层嵌套时,
json_decode性能比循环遍历好得多
已有对象数组时用 json_encode + json_decode 组合转换
当手头已经是 PHP 对象数组(例如 [$obj1, $obj2]),且对象属性都是 public 的,可以先序列化再反解:
$arr = json_decode(json_encode($objArray), true);
这招本质是把对象“扁平化”成 JSON 再还原为数组,能处理多层嵌套对象。
立即学习“PHP免费学习笔记(深入)”;
但要注意:private/protected 属性会被丢弃;含 Closure、resource、PDO 实例等不可序列化内容会失败并返回 null。
- 适合临时调试或数据导出场景,别在高频循环里用(JSON 编解码有开销)
- 若对象来自 Doctrine 或 Laravel Eloquent,优先用
toArray()方法,更安全可靠 - 遇到
Recursion detected错误,说明对象里有循环引用,得先用__sleep或手动剥离
手动递归转换对象数组(可控但需谨慎)
需要保留 private/protected 属性,或处理不可序列化对象时,只能自己写递归函数。核心逻辑是判断类型 + 强制类型转换:
function objectToArray($obj) {
if (is_object($obj)) $obj = (array) $obj;
if (is_array($obj)) {
return array_map('objectToArray', $obj);
}
return $obj;
}
(array) 强转会把 public 属性转为键值,private 属性变成 "\0Classname\0prop" 这种格式,可读性差。
- 若要清理这些魔术键名,得额外用
preg_replace去掉\0字节 - 不推荐用于生产环境的通用转换,容易因魔术方法(如
__get)行为不一致导致数据丢失 - laravel 的
Arr::dot()或Arr::undot()更适合做“扁平 ↔ 嵌套”结构转换,而非对象转数组
为什么不用 get_object_vars 直接转?
get_object_vars 只能取 public 属性,且不递归,对多层对象数组基本无效。比如 $arr[0]->user->profile->name,它最多拿到第一层 user 对象,后面还是对象。
有人试图嵌套调用:get_object_vars(get_object_vars($obj)['user']),但这样写脆弱、难维护,也处理不了数组中混有对象和标量的情况。
- 它连继承链上的父类 public 属性都拿不到(除非对象本身定义了)
- 遇到 __get/__set 重载时,返回结果可能和实际访问
->不一致 - 真正需要精细控制字段映射时,应该在对象内部定义
toArray()方法,而不是依赖外部函数硬转
最常被忽略的是对象里的 DateTime、Carbon、Closure 等非标量类型——它们不会自动转成字符串或数组,强行 json_encode 会静默失败。动手前先 var_dump 看清结构,比盲目套用转换函数更重要。



















