PHP递归练习:如何将JSON转为指定格式的关联数组
解决JSON转路径式键名关联数组的问题
首先,咱们先明确你的需求:把嵌套的JSON结构转换成以路径为键、对应值为值的扁平关联数组,同时你还想知道如何只保留关联索引对应的条目。我来一步步帮你修改递归函数,实现这两个需求。
一、修改递归函数构建目标数组
首先,你需要先把JSON字符串解码成PHP数组,然后通过递归遍历,维护当前的路径前缀,把每个标量值的完整路径作为键存入结果数组。这里关键是用引用传递来维护结果数组,避免每次递归重新创建数组。
完整代码示例:
<?php $json_str = '{ "one": { "two": 3, "four": [ 5,6,7] }, "eight": { "nine": { "ten":11 } } }'; // 解码JSON为关联数组 $data = json_decode($json_str, true); /** * 扁平化嵌套数组,生成路径式键名的关联数组 * @param array $array 要处理的嵌套数组 * @param string $prefix 当前路径前缀 * @param array &$result 结果数组(引用传递) * @return array 扁平化后的数组 */ function flattenArray($array, $prefix = '', &$result = []) { foreach ($array as $key => $value) { // 构建当前完整路径:前缀不为空时用"前缀/键",否则直接用键 $currentPath = $prefix ? "{$prefix}/{$key}" : $key; if (is_array($value)) { // 如果是子数组,递归处理,把当前路径作为新前缀传入 flattenArray($value, $currentPath, $result); } else { // 如果是标量值,把路径作为键、值作为值存入结果数组 $result[$currentPath] = $value; } } return $result; } // 调用函数得到目标数组 $flattenedArray = flattenArray($data); print_r($flattenedArray); ?>
运行这段代码后,你就能得到想要的结果:
Array ( [one/two] => 3 [one/four/0] => 5 [one/four/1] => 6 [one/four/2] => 7 [eight/nine/ten] => 11 )
二、仅获取关联索引对应的条目
如果想要排除索引数组(数字键的数组)中的元素,只保留来自关联数组的条目(比如上面例子中的one/two和eight/nine/ten),我们需要先判断数组是否为关联数组,再在递归中过滤掉索引数组的内容。
步骤1:编写关联数组判断函数
首先写一个工具函数,用来区分关联数组和索引数组:
/** * 判断是否为关联数组 * @param array $array 要判断的数组 * @return bool 是关联数组返回true,否则返回false */ function isAssocArray($array) { // 如果数组的键不是从0开始连续的数字,就是关联数组 return is_array($array) && array_keys($array) !== range(0, count($array) - 1); }
步骤2:修改递归函数过滤索引数组
基于之前的扁平化函数,修改成只处理关联数组的版本:
/** * 扁平化嵌套数组,仅保留关联索引对应的条目 * @param array $array 要处理的嵌套数组 * @param string $prefix 当前路径前缀 * @param array &$result 结果数组(引用传递) * @return array 过滤后的扁平化数组 */ function flattenAssocOnly($array, $prefix = '', &$result = []) { foreach ($array as $key => $value) { $currentPath = $prefix ? "{$prefix}/{$key}" : $key; if (is_array($value)) { // 只有当前数组是关联数组时,才递归处理子元素 if (isAssocArray($value)) { flattenAssocOnly($value, $currentPath, $result); } } else { // 只有当前键不是数字(属于关联数组的键)时,才存入结果 if (!is_numeric($key)) { $result[$currentPath] = $value; } } } return $result; } // 调用函数 $assocOnlyArray = flattenAssocOnly($data); print_r($assocOnlyArray);
运行后得到的结果就是仅保留关联索引的条目:
Array ( [one/two] => 3 [eight/nine/ten] => 11 )
补充说明
如果你的“关联索引”指的是其他逻辑(比如只保留特定前缀的路径),可以根据需求调整判断条件,比如在存入结果时检查路径是否符合特定规则即可。
内容的提问来源于stack exchange,提问作者ponytails_soda
相关产品推荐
相关产品推荐

