php 本身无内置 json 深度限制,需在递归函数中手动控制:每次递归 $depth++ 并传入 $depth + 1,初始调用显式传 0 或 1,阈值建议 ≤100;须统一判断 array/stdclass 类型,解码只做一次,超限时返回带 'truncated' 标记的结构而非 null 或 false。

递归函数里加个 $depth 参数最直接
PHP 本身没有内置 JSON 深度限制,得自己在递归逻辑里控制。核心就是每次进一层就 $depth++,到达阈值就提前 return,不继续往下走。
常见错误是只检查当前层级是否超限,却忘了在递归调用时没传入更新后的深度值,结果永远卡在第一层判断。
- 初始调用必须显式传
0或1(看你是从 0 开始计还是从 1 开始) - 每进一层递归,必须传
$depth + 1,不能漏掉 - 阈值建议设为
100以内,PHP 默认栈深度有限,过深容易触发Fatal error: Maximum function nesting level
遇到数组/对象混嵌要统一判断结构类型
JSON 解码后可能是 array 或 stdClass,但 is_array() 对 stdClass 返回 false,直接用 is_iterable() 会误判字符串(PHP 8+),稳妥做法是先 is_array() 再 is_object() 并检查是否可遍历。
容易踩的坑:用 foreach 遍历 stdClass 是可以的,但如果你写了 if (is_array($item)) { ... } 就会跳过对象字段,导致深层对象被忽略。
- 推荐用
is_array($data) || (is_object($data) && $data instanceof \stdClass) - 或者更通用:用
json_last_error() === JSON_ERROR_NONE确保解码成功后再处理 - 别依赖
gettype(),它返回object但不区分stdClass和其他类实例
用引用传递避免重复解码或意外修改原始数据
如果 JSON 数据很大,又在多处递归调用中反复 json_decode($json, true),性能会明显下降;更危险的是,如果递归中直接修改了传入的数组引用,原始数据可能被污染。
典型场景:你传了个 $data 进去,中间某层做了 $data['key'] = 'new',上层拿到的就是改过的值。
- 解码只做一次,把结果传给递归函数,而不是每次都重新
json_decode() - 如需安全遍历不修改原数据,传参时用
clone或array_merge([], $data)(仅限一维数组) - 对
stdClass对象,clone有效;但深层对象需手动递归 clone,不如一开始就用json_decode($json, true)得到纯数组
超过层级后怎么返回才不算“失败”
很多实现一超限就 return false 或抛异常,结果调用方没法区分“到底有没有数据”和“只是太深”。更实用的做法是返回一个带标记的结构,比如 ['truncated' => true, 'data' => $current]。
否则前端看到空数组,根本不知道是 JSON 为空,还是因为深度截断了。
- 不要用
null或false表示截断,语义不清 - 可以在返回值里加
'max_depth_reached' => true字段,方便上层做 fallback 处理 - 如果业务允许,也可以把截断点的键名记下来,比如
'stopped_at' => ['user', 'profile', 'preferences']
深度控制不是越严越好,关键是让调用方知道发生了什么。真遇到 20 层嵌套的 JSON,先确认是不是设计问题,再决定是调高阈值,还是改用流式解析。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











