PHP如何基于动态深度选择器从JSON中生成对应多层级数组
实现方案
核心逻辑是基于路径分段动态读取原数组值,同时动态创建结果数组的对应层级,全程不需要提前感知数组结构和选择器深度,具体实现如下:
完整可运行代码
<?php function filterBySelector(string $json, string $selector): array { $originArr = json_decode($json, true); if (json_last_error() !== JSON_ERROR_NONE) { return []; } $result = []; // 拆分多个选择器 $selectorItems = explode(',', $selector); foreach ($selectorItems as $item) { $item = trim($item); if (empty($item)) continue; // 拆分路径段 $pathSegments = explode('.', $item); $segCount = count($pathSegments); if ($segCount < 1) continue; // 第一步:从原数组读取对应路径的值 $currentOrigin = $originArr; $valueExists = true; foreach ($pathSegments as $seg) { // 兼容数字索引和字符串键 $key = is_numeric($seg) ? (int)$seg : $seg; if (!isset($currentOrigin[$key])) { $valueExists = false; break; } $currentOrigin = $currentOrigin[$key]; } if (!$valueExists) continue; $targetValue = $currentOrigin; // 第二步:动态创建结果数组层级,写入值 // 层级路径为去掉最后一段索引的所有路径段 $levelSegments = array_slice($pathSegments, 0, $segCount - 1); $currentResult = &$result; foreach ($levelSegments as $seg) { $key = is_numeric($seg) ? (int)$seg : $seg; // 不存在的层级自动创建空数组 if (!isset($currentResult[$key]) || !is_array($currentResult[$key])) { $currentResult[$key] = []; } $currentResult = &$currentResult[$key]; } // 把值追加到对应层级的数组末尾 $currentResult[] = $targetValue; // 释放引用避免污染后续循环 unset($currentResult); } return $result; } // 测试用例1:原始3层路径场景 $json = ' { "hotels" : { "hotel" : [ { "ort": "rom", "lioc": "inrom" }, { "ort": "paris", "lioc": "inpsrisd" }, { "ort": "berlin", "lioc": "inberlin" }, { "ort": "milano", "lioc": "inmilano" }, { "ort": "paris", "lioc": "anotherinpsrisd" }, { "ort": "muc", "lioc": "inmuc" } ] } }'; $selector = "hotels.hotel.0,hotels.hotel.5"; $result = filterBySelector($json, $selector); echo json_encode($result) . PHP_EOL; // 输出结果:{"hotels":{"hotel":[{"ort":"rom","lioc":"inrom"},{"ort":"muc","lioc":"inmuc"}]}} // 测试用例2:深层级路径场景 $deepJson = '{"hotels":{"hotel":{"bla":{"bla":[{"ort":"rom","lioc":"inrom"},{},{},{},{},{"ort":"muc","lioc":"inmuc"}]}}}}'; $deepSelector = "hotels.hotel.bla.bla.0,hotels.hotel.bla.bla.5"; $deepResult = filterBySelector($deepJson, $deepSelector); echo json_encode($deepResult) . PHP_EOL; // 输出结果:{"hotels":{"hotel":{"bla":{"bla":[{"ort":"rom","lioc":"inrom"},{"ort":"muc","lioc":"inmuc"}]}}}}
逻辑说明
- 先对输入JSON做合法性校验,避免解析失败抛出异常
- 拆分选择器为多个独立路径,逐路径做校验和取值
- 逐段遍历路径从原数组读取目标值,路径不存在直接跳过当前选择器
- 取路径的前N-1段作为结果数组的层级路径,通过PHP引用特性动态创建不存在的层级
- 最终把读取到的目标值追加到对应层级的数组末尾,保证结构完全匹配选择器层级
- 全程兼容字符串键、数字索引,无需提前知晓JSON结构和选择器深度
内容的提问来源于stack exchange,提问作者Web Star
相关产品推荐
相关产品推荐

