PHP递归JSON儿童搜索

时间:2016-12-25 07:11:06

标签: php loops recursion logic

我需要解析看起来像这样的JSON:

{
    "mdfId":"282088127",
    "mdfConcept":"ME 3400EG-12CS-M Switch",
    "children":[
        {
            "mdfId":"007",
            "mdfConcept":"Another item",
            "children": [
                // many more here
            ]
        },
        {
             "mdfId":"008",
             "mdfConcept":"Another one",
             "children": [
                 {
                     "mdfId":"010",
                     "mdfConcept":"What I'm looking for!",
                     "children": [] // no children
                 }
             ]
        },
        // many more here
    ]
},

这是一个递归结构,其中每个元素都有mdfIdmdfConceptchildren个键。

假设我需要在此结构中找到ID=010的节点。我不知道它在哪个级别(例如,它可能位于顶层,或下面的几个children节点。

我目前的做法是:

$mdfId = '010'; // what I'm loking for

foreach ($jsonResponse as $category) {
    while (true) {
        if ($category['mdfId'] == $mdfId) {
            // we found it!
            $categoryDevices[$mdfId] = $category['children'];
            break 2;
        }

        if (!empty($category['children'])) {
            next_cat:

            if (is_null($category['children'])) {
                break;
            }

            $category = array_shift($category['children']);
            continue;
        }

        if (empty($category['children'])) {
            goto next_cat;
        }
    }
}

但目前的方法错过了一些案例。如何优化此递归循环,以便检查同一级别的所有节点,并且每个节点可通过任意数量的children密钥进行访问?

2 个答案:

答案 0 :(得分:1)

JSON对象的一个​​令人尴尬的特点是,虽然每个children成员都是" child"结构,顶层一个是对象本身,因此它是真正递归方法的障碍。

我们可以通过将源JSON对象转换为与嵌套级别相同的结构来解决,例如:

  • $jsonResponse作为原始对象
  • 使用['children' => $jsonResponse]代替

这样,它应该可以使用这样的东西:

$mdfId = '010'; // what I'm loking for

if ($result = look4id(['children' => $jsonResponse], $mdfId) {
    $categoryDevices[$mdfId] = $result;
}

function look4id($source, $id) {
    foreach ($source as $child) {
        if ($child['mdfId'] == $id) {
            return $source['children'];
        } else {
            if ($source['children']) {
                return look4id($source['children'], $id);
            }
        }
    }
}

答案 1 :(得分:0)

所以基本上我写了一个函数,它没有返回任何东西,而是从参数填充变量。

function findRecursiveArrayNodeById($id, $array, &$node) {
    foreach ($array as $child) {
        if (isset($child['mdfId']) && $child['mdfId'] == $id) {
            $node = $child;
            return;
        }

        if (!empty($child['children'])) {
            findRecursiveArrayNodeById($id, $child['children'], $node);
        }
    }
}

用法如下:

$result = false;

findRecursiveArrayNodeById($mdfId, $category_json, $result);

if (!$result) {
    println("did not find {$mdfId}");
    continue;
}