17370845950

如何在 PHP 中动态创建包含多个 JSON 对象元素的嵌套结构

本文详解如何使用 php 动态构建符合特定嵌套格式的 json 数据,重点解决多条路由(routes)及其地理坐标(geom)数组的程序化生成问题,并修正原始代码中因对象重复赋值导致仅保留最后一项的典型错误。

在 PHP 中构建结构化 JSON 数据时,一个常见误区是将新对象反复赋值给同一变量(如 $json->route_ID = ...),这会导致前序数据被覆盖——正如原代码中最终只输出 route_ID: "50" 所示。正确做法是将每条路由作为独立元素追加到数组中,再整体封装为 Routes 键下的 JSON 数组。

以下是优化后的完整实现:

147.499935,-30.63607 "},{"route_ID":"50","geom":"147.499935,-30.63607"}]';

// 1. 解析原始 JSON 字符串为关联数组
$jsonArray = json_decode($jsonString, true);

// 2. 初始化顶层容器对象
$json_Routes = new stdClass();
$json_Routes->Routes = []; // ✅ 关键:初始化为数组,而非对象或 null

// 3. 遍历每条路由记录,逐个构建并追加
foreach ($jsonArray as $record) {
    // 解析 geom 中的坐标字符串(支持空格/换行分隔的多组坐标)
    $geomString = $record["geom"];
    $geomString = preg_replace('/|<\/coordinates><\/LineString>/i', '', $geomString);
    $geomString = trim($geomString);

    // 拆分坐标对(兼容含空格、制表符、换行的格式)
    $coords = preg_split('/\s+/', $geomString, -1, PREG_SPLIT_NO_EMPTY);
    $route_geom = [];

    foreach ($coords as $coord) {
        if (strpos($coord, ',') !== false) {
            [$lng, $lat] = array_map('trim', explode(',', $coord));
            $route_geom[] = [
                'lat' => $lat,
                'lng' => $lng
            ];
        }
    }

    // 构建单条路由对象(使用关联数组更直观,后续 json_encode 自动转为对象)
    $route = [
        'route_ID' => $record['route_ID'],
        'geom'     => $route_geom
    ];

    // ✅ 追加到 Routes 数组(非覆盖赋值)
    $json_Routes->Routes[] = $route;
}

// 4. 输出标准化 JSON(带缩进便于调试)
echo json_encode($json_Routes, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
?>

关键改进点说明:

  • $json_Routes->Routes = []:显式初始化为空数组,确保后续 [] 操作可安全追加;
  • 避免重复赋值对象属性:不再用 $json->route_ID = ... 覆盖同一变量,而是每次新建 $route 数组;
  • 健壮的坐标解析:使用 preg_split('/\s+/', ...) 替代 explode(' '),兼容多空格、换行等不规则分隔;
  • 类型安全处理:array_map('trim', ...) 清除坐标前后空格,防止解析异常;
  • 输出优化:JSON_PRETTY_PRINT 提升可读性,JSON_UNESCAPED_UNICODE 避免中文乱码(如有)。

注意事项:

  • 原始 $jsonString

    中 geom 的坐标格式为 lng,lat(经度在前),而目标 JSON 要求 "lat" 和 "lng" 字段,因此赋值时需严格按 $var[1](纬度)、$var[0](经度)顺序映射;
  • 若实际数据中存在无效坐标(如缺失逗号、非数字字符),建议增加 is_numeric() 校验与异常处理;
  • 如需更高性能或处理海量数据,可考虑使用 json_decode($jsonString) 返回对象后直接遍历,避免 true 参数带来的数组开销。

通过以上重构,即可稳定生成符合要求的嵌套 JSON 结构,且具备良好的可维护性与扩展性。