json_decode() 不自动重建关系,需手动维护层级;递归丢失 children 是因未传引用或未赋值回原位置;应统一转数组、用引用参数、路径标记、栈迭代防爆栈。

不会自动保持——json_decode() 只负责“解开”,不负责“重建关系”;层级结构是否完整,完全取决于你后续怎么遍历、怎么挂载、怎么传引用。
递归遍历时为什么 children 会丢失?
常见现象:明明原始 JSON 里有 "children" 字段,但递归函数一跑,输出里就没了,或者所有子节点都挤在根数组里。
- 根本原因不是递归写错了,而是你在递归过程中没把子结构“塞回去”——比如只读取了
$item['children'],却没把它作为参数传给下一层,也没赋值回原位置 - 用
foreach ($data as $key => $value)遍历时,$value是副本,修改它不影响原数组;必须用引用&$value或显式赋值$data[$key] = ... - 如果源数据是对象(
json_decode($json)默认返回对象),而你用数组语法$obj['children']访问,会静默失败,得用$obj->children或统一转成数组
怎么安全地递归修改嵌套 JSON 数据?
目标是边遍历边改值、加字段、删键,同时不破坏原有层级和引用关系。
- 入口处统一用
json_decode($json, true)转成关联数组,避免对象/数组混用判断 - 递归函数接收 & 引用参数:
function traverse(&$data, $callback),这样内部修改直接生效 - 对每个值调用
$callback($value, $key, $path),其中$path是类似"menu.items.0.label"的字符串,便于定位 - 遇到数组时,先递归处理子项,再把结果写回:
foreach ($data as $k => &$v) { traverse($v, $callback); } - 别在回调里直接
unset($data[$k])——PHP 数组遍历时删除键可能导致跳过下一元素;改用标记 + 后续清理,或换用array_filter()配合键名回调
大嵌套 JSON 递归容易爆栈?换迭代方式
当 JSON 层级超过 200 层,或节点数上万时,纯递归极易触发 Maximum function nesting level 错误或内存耗尽。
- 用栈(stack)模拟递归:初始化一个包含根节点和空路径的数组,
while (!empty($stack))循环出栈、处理、把子节点压栈 - 每层只存必要信息:例如
['data' => $node, 'path' => $current_path],避免闭包或深拷贝带入额外开销 - 提前限制最大深度:在压栈前检查
count(explode('.', $path)) > 100,超限则跳过或报错,防恶意深层 JSON 攻击 -
json_decode()自身也受$depth参数限制(默认 512),若原始 JSON 嵌套过深,需显式传参:json_decode($json, true, 1024)
真正卡住的往往不是“怎么写递归”,而是没意识到:JSON 层级是数据结构决定的,不是算法决定的;你传进去的是扁平数组,再深的递归也变不出 children 字段。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











