json_encode()不会丢失层级,前提是php数组已是正确嵌套结构;若数据为扁平id+parent_id格式,需手动构建children嵌套树,再调用json_encode()输出。

PHP 用 json_encode() 直接输出树形结构会丢层级?
不会丢,但前提是你的 PHP 数组本身已经是正确的嵌套结构。很多人以为 json_encode() 有“树形处理模式”,其实它只忠实地序列化数组/对象的当前形状——如果源数据是扁平的 ID + parent_id 列表,那 JSON 当然也是扁平的。
常见错误现象:json_encode() 出来的是一维数组,前端拿不到 children 字段;或者所有节点都挂在根下,层级全乱了。
- 先确认原始数据是不是已经组织成「父元素含 children 数组」的嵌套格式(不是数据库查出的扁平记录)
- 如果不是,别指望
json_encode()自动帮你转——它不解析 parent_id,也不递归建树 - 数据库查出来的扁平结果,必须手动用 PHP 构建嵌套数组,再交给
json_encode()
怎么把扁平数组(含 parent_id)转成嵌套树?
这是最常卡住的地方:拿到的是类似 [['id'=>1,'name'=>'A','parent_id'=>0], ['id'=>2,'name'=>'B','parent_id'=>1]] 这种,需要变成带 children 的多层结构。
核心思路是两遍遍历:第一遍用 id 做键存所有节点,第二遍按 parent_id 挂载到对应父节点的 children 里。
立即学习“PHP免费学习笔记(深入)”;
- 避免用递归函数处理大数组(比如上万节点),容易爆栈或超时;迭代方式更稳
- 确保 parent_id 字段值和目标父节点的 id 类型一致(都是 int 或都是 string),否则
isset($map[$row['parent_id']])会失效 - 根节点的
parent_id通常为 0 或 null,要统一判断逻辑,别混用
简短示例:
$map = [];<br>$tree = [];<br>foreach ($flat as $row) {<br> $map[$row['id']] = $row + ['children' => []];<br>}<br>foreach ($flat as $row) {<br> if ($row['parent_id'] == 0) {<br> $tree[] = &$map[$row['id']];<br> } else {<br> $map[$row['parent_id']]['children'][] = &$map[$row['id']];<br> }<br>}
json_encode() 输出中文乱码或 \uXXXX?
不是树形结构的问题,是编码没设对。PHP 默认把非 ASCII 字符转成 Unicode 转义,看着像乱码,其实是合法 JSON,但可读性差、调试麻烦。
- 加
JSON_UNESCAPED_UNICODE参数就能保留原文汉字:json_encode($data, JSON_UNESCAPED_UNICODE) - 确保 PHP 文件本身是 UTF-8 编码(无 BOM),且数据库连接字符集也是 utf8mb4
- 如果用了
iconv()或mb_convert_encoding()中途转码,反而可能引入不可见字符,导致json_encode()返回 false
前端渲染树形结构时发现 children 是空数组,但 PHP 里明明有?
大概率是 PHP 数组里混入了空字符串、null 或未初始化的 children 键,而 json_encode() 把空数组照常输出,但前端框架(比如 Vue 的 v-for)遇到空 children 可能直接跳过渲染分支。
- 构建树时,每个节点都显式初始化
'children' => [],别依赖隐式赋值 - 检查是否用了
array_filter()之类函数清理数据,它默认会过滤掉空数组,导致 children 消失 - 用
json_last_error_msg()验证输出是否完整,有时 JSON 失败静默返回 false,你却在 echo 空字符串
树形数据的关键不在 JSON 本身,而在 PHP 数组构建那一刻是否真正完成了父子引用。一旦嵌套结构错了,后面怎么 encode 都救不回来。











