PHP 递归 JSON 子项搜索
Posted
技术标签:
【中文标题】PHP 递归 JSON 子项搜索【英文标题】:PHP Recursive JSON Children Search 【发布时间】:2017-05-10 05:08:39 【问题描述】:我需要解析如下所示的 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
]
,
这是一个递归结构,其中每个元素都有mdfId
、mdfConcept
和children
键。
假设我需要在这个结构中找到带有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
键访问?
【问题讨论】:
【参考方案1】:您的 JSON 对象的一个令人尴尬的特性是,虽然每个 children
成员都是“子”结构的数组,顶层是对象本身,所以这是一个障碍真正的递归方法。
我们可以通过将源 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);
【讨论】:
总体上很好的答案和方法。允许我将发现率从 30% 提高到 60%。但是,一旦循环进入多个children
深度,它就会忘记更高级别上未触及的元素。因此,如果007
和008
以相反的顺序放置,脚本将检查008
及其子010
,但完全错过了007
。
@DenisBobrovnikov 哼...有趣的问题!您能否发布一个 JSON 对象的示例,如果不是太重,找不到哪个键? (您可以编辑您的 OP 并将对象放入 SO sn-p)【参考方案2】:
所以基本上我编写了一个不返回任何内容的函数,而是从参数中填充了一个变量。
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;
【讨论】:
以上是关于PHP 递归 JSON 子项搜索的主要内容,如果未能解决你的问题,请参考以下文章