【问题标题】:Encode nested array to proper json without array indexes将嵌套数组编码为没有数组索引的正确 json
【发布时间】:2012-08-21 00:33:57
【问题描述】:

我有一个示例 2d $tasks 数组,它描述了一个嵌套结构:

Array
(
    [14] => Array
        (
            [Id] => 14
            [parentId] => null
            [Name] => T1
        )

    [40] => Array
        (
            [Id] => 40
            [parentId] => null
            [Name] => T5
        )

    [41] => Array
        (
            [Id] => 41
            [parentId] => null
            [Name] => T4
        )

    [22] => Array
        (
            [Id] => 22
            [parentId] => 14
            [Name] => T2
        )

    [43] => Array
        (
            [Id] => 43
            [parentId] => 22
            [Name] => T2 child
        )

    [42] => Array
        (
            [Id] => 42
            [parentId] => 14
            [Name] => T3
        )

)

使用下面的代码,我将其转换为适当的树结构:

$sortedArray = array();
// get first level
foreach($tasks as $k => $v){
    if($v['parentId'] == 'null'){
        $sortedArray[$k] = $v;
        unset($tasks[$k]);
    }
}
// sort parents
asort($sortedArray);

function getChildren(array & $a1, array & $a2){
    foreach($a1 as $k => $v){
        findChildren($v, $a2, $k);      
    }
}

function findChildren($rec1, array & $a2, $key){

    foreach($a2 as $k => $v){
        if($rec1['parentId'] == $v['Id']){
            $a2[$k]['children'][$rec1['Id']] = $rec1;
            unset($tasks[$key]);
        } else {
            if (isset($v['children'])){
                findChildren($rec1, $a2[$k]['children'], $key);
            }
        }
    }
}

findChildren($tasks, $sortedArray);

运行此代码后输出$sortedArray 如下所示:

Array
(
    [14] => Array
        (
            [Id] => 14
            [parentId] => null
            [Name] => T1
            [children] => Array
                (
                    [22] => Array
                        (
                            [Id] => 22
                            [parentId] => 14
                            [Name] => T2
                            [children] => Array
                                (
                                    [43] => Array
                                        (
                                            [Id] => 43
                                            [parentId] => 22
                                            [Name] => T2 child
                                        )

                                )

                        )

                    [42] => Array
                        (
                            [Id] => 42
                            [parentId] => 14
                            [Name] => T3
                        )

                )

        )

    [40] => Array
        (
            [Id] => 40
            [parentId] => null
            [Name] => T5
        )

    [41] => Array
        (
            [Id] => 41
            [parentId] => null
            [Name] => T4
        )

)

问题是,在当前状态下对该输出数组调用 json_encode 后,我得到了:

{"14":{"Id":"14","parentId":"null"...

所以所有嵌套数组都插入了它们的索引。我知道我可以使用array_values 修复第一级。但是有没有任何简单的方法可以为所有级别做到这一点?没有它,我最终会得到 'children' 不是一个数组,而是一个令我不满意的对象。

【问题讨论】:

  • 无论如何,您的数组元素将有一些初始无序或有序索引(从 0 开始),json_encode 会将它们转换为 JSON 属性
  • 你确定吗?使用 json_encode(array_values($array)) 创建一个令我满意的 javascript 对象数组,并且索引丢失,这也很好。

标签: php arrays json


【解决方案1】:

您的帖子中没有代码,但 $tasks 是作为关联数组创建的。在您的示例中,您还可以像使用关联数组一样遍历 $tasks

foreach($tasks as $k => $v){
    ...
}

您需要像使用数值数组一样将子级添加到$tasks;区别在于:

//associative array
$test = array();
$test["43"] = "hello";
$test["40"] = "hello1";
$test["23"] = "hello2";
print_r($test);

//numeric array
$testb = array(); 
$testb[] = "hello";
$testb[] = "hello1";
$testb[] = "hello2";
print_r($testb);

现场示例:http://codepad.org/tsOhX88h

对于数值数组,您作为问题 {"14":{"Id":"14","parentId":"null"... 引用的顶级索引(例如 14)不再存在。

作为一个简单的最后一步,使用以下代码将关联数组中的项推送到新的数值数组中:

$finalArray = array();
foreach ($sortedArray as $key=>$val ){
    $finalArray[] = $sortedArray[$key];
}
print_r($finalArray);

现场示例:http://codepad.org/uSGSr1DC

或者您可以使用array_values 一次性完成:

$finalArray = array();
$finalArray = array_values($sortedArray);
print_r($finalArray);

现场示例:http://codepad.org/D7uBSRr8

【讨论】:

  • 好的,但是如果我不使用 assoc 数组,我将无法使用我现在使用的代码从平面数组中创建树结构。
【解决方案2】:

如果你碰巧这样做,你没有包括你的 json_encode 调用......

json_encode(array_values($sortedArray), JSON_FORCE_OBJECT);

那么强制将无论如何都会放入数字索引。 不确定这是否会对您有所帮助,但它可能会帮助遇到同样问题的其他人。

【讨论】:

    【解决方案3】:

    好的,所以我能够想出这样的东西:

    function makeIndexed(array & $arr, array & $par = null){
        if(is_null($par)){
            $arr = array_values($arr);
        } else {
            $par['children'] = array_values($arr);
        }
    
        for($i=0; $i<count($arr); $i++) {   
            $temp = @$arr[$i]['children'];
            if(isset($temp)) {
                makeIndexed($arr[$i]['children'], $arr[$i]);
            }       
        }
    }
    

    现在调用makeIndexed($sortedArray); 给了我一个有效的JSON,其中'children' 是一个节点数组而不是一个对象。我知道这段代码可能很丑陋并且缺乏性能,但至少会产生正确的结果。如果有人可以创建更简洁/更短的内容,我很乐意将其标记为正确答案。

    【讨论】:

    • 为什么要使用for 循环?您只需使用一次array_valuesarray_values 将返回一个数字数组,该数组维护所有嵌套结构并删除顶层。你看过我的示例代码吗? codepad.org/pIjA95rG
    • 是的,但这不起作用。不确定您是否已经用更多级别测试了您的案例。就我而言,它仅适用于第一级。
    • array_values 与其他嵌套级别一起使用:codepad.org/D7uBSRr8 但我也更新了我的答案以包含foreach 方法。
    猜你喜欢
    • 2015-01-29
    • 1970-01-01
    • 1970-01-01
    • 2022-01-16
    • 2012-08-13
    • 2022-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多