PHP 如何遍历 JSON 中的 features 并获取当前和下一项的 city?
可以在 foreach 中取得当前数组索引,再通过 $features[$i + 1] 读取下一项。索引访问不会改变外层循环的遍历进度,因此会依次配对第 1、2 项,第 2、3 项,第 3、4 项,以此类推。
为什么可以通过索引访问下一项
按题目中的调用方式,json_decode($file) 会将 JSON 对象解析为对象,将 JSON 数组解析为 PHP 数组。因此:
$path是对象,使用->features访问属性。$path->features是数组,使用[0]、[1]等索引访问元素。- 每个 feature 及其
properties是对象,使用->properties->city访问 city。
如果只需要第二个 feature 的 city,可以直接读取:
$city = $path->features[1]->properties->city;
题目中该值为 YYY。数组索引从 0 开始,所以第二项的索引是 1。
保留 foreach,逐次读取相邻两项
下面的代码会读取文件、解析 JSON 并检查 features 的类型。循环部分假设每个 feature 都具有题目所示的 properties.city 结构。
<?php
$file = file_get_contents('file.json');
if ($file === false) {
exit("无法读取 file.json\n");
}
$path = json_decode($file);
if (JSON_ERROR_NONE !== json_last_error()) {
exit(json_last_error_msg() . "\n");
}
if (!isset($path->features) || !is_array($path->features)) {
exit("JSON 中缺少 features 数组\n");
}
$features = $path->features;
foreach ($features as $i => $routes) {
// 最后一项没有下一项,不再组成配对。
if (!isset($features[$i + 1])) {
break;
}
$start = $routes->properties->city;
$finish = $features[$i + 1]->properties->city;
printf("%s -> %s\n", $start, $finish);
}
对于题目中的两项数据,输出为:
XXX -> YYY
$routes 是当前项,$features[$i + 1] 是下一项。读取下一项后,下一次 foreach 循环仍会从原本的下一项开始。
最后一项如何处理
最后一项没有后继元素,因此不能再组成相邻配对。包含 n 个有效 feature 的数组会得到 n - 1 组配对;空数组或只有一项的数组不会产生配对。
示例中的 isset() 检查适用于题目给出的 feature 对象数组。如果数组可能包含 null,或者 feature 缺少 properties.city,需要根据实际数据规则决定报错还是跳过。跳过异常项可能改变预期的配对关系。
配对使用的是 features 的数组顺序。properties.step 不参与索引计算,也不会自动决定遍历顺序。
原代码还需要修正的语法
原片段在 JSON 错误检查之后多了一个 };给 $start 赋值时,末尾也多了一个 )。正确写法是:
$start = $routes->properties->city;
PHP 变量名需要以 $ 开头,所以应使用 $finish。完成下一项的边界检查后,将赋值部分改为下面两行,即可取得当前项和下一项的 city:
$start = $routes->properties->city;
$finish = $features[$i + 1]->properties->city;
备注:内容仅供参考。
