PHP从SQL Server生成GeoJSON报错:geometry应为对象而非字符串
解决GeoJSON中geometry为字符串而非对象的问题
你遇到的核心问题是:直接把SQL返回的WKT字符串塞进了GeoJSON的geometry字段,但GeoJSON规范明确要求geometry必须是包含type和coordinates的对象,而非字符串。下面是具体的修复方案:
问题根源分析
你当前生成的结果里,geometry是类似这样的字符串:
"geometry":"\"MULTILINESTRING ((-77.083060324719384 42.15108721847372, ...))"
但标准GeoJSON要求的结构应该是:
"geometry": { "type": "MULTILINESTRING", "coordinates": [ [[-77.08306, 42.15109], [-77.08745, 42.15177], ...] ] }
手动解析修复代码示例
针对你用到的MULTILINESTRING类型,我们可以手动把WKT字符串解析成符合要求的geometry对象,代码如下:
<?php // 假设你已建立数据库连接$conn $sql = "SELECT name, pwl_id, wbcatgry, basin, fact_sheet, geom.STAsText() as geo FROM dbo.total"; $stmt = sqlsrv_query($conn, $sql); $features = []; while ($res = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { $wkt = $res['geo']; // 用正则提取WKT的几何类型和坐标部分 preg_match('/^(\w+)\s*\((.*)\)$/', $wkt, $matches); $geometryType = strtoupper($matches[1]); $coordsRaw = $matches[2]; // 初始化geometry对象 $geometry = ['type' => $geometryType]; // 处理MULTILINESTRING的坐标转换 if ($geometryType === 'MULTILINESTRING') { // 拆分每个线串的坐标组 $lineGroups = explode('), (', trim($coordsRaw, '()')); $coordinates = []; foreach ($lineGroups as $line) { $points = explode(', ', $line); $lineCoords = []; foreach ($points as $point) { // 拆分经纬度并转为浮点型(注意GeoJSON是[经度, 纬度]顺序) list($lon, $lat) = explode(' ', trim($point)); $lineCoords[] = [(float)$lon, (float)$lat]; } $coordinates[] = $lineCoords; } $geometry['coordinates'] = $coordinates; } // 扩展提示:如果需要支持POINT、LINESTRING、POLYGON等类型,可添加对应的解析逻辑 // 构建Feature对象 $feature = [ 'type' => 'Feature', 'properties' => [ 'name' => $res['name'], 'pwl_id' => $res['pwl_id'], 'wbcatgry' => $res['wbcatgry'], 'basin' => $res['basin'], 'fact_sheet' => $res['fact_sheet'] ], 'geometry' => $geometry ]; $features[] = $feature; } // 组装成标准的GeoJSON FeatureCollection结构 $geoJson = [ 'type' => 'FeatureCollection', 'features' => $features ]; // 输出GeoJSON header('Content-Type: application/json'); echo json_encode($geoJson); // 清理资源 sqlsrv_free_stmt($stmt); sqlsrv_close($conn); ?>
简化方案:使用geoPHP库
如果你的项目需要支持多种几何类型,手动解析会比较繁琐,可以借助geoPHP库自动处理WKT到GeoJSON的转换:
- 先通过Composer安装geoPHP:
composer require phayes/geophp
- 然后替换代码中的解析逻辑:
// 引入geoPHP require 'vendor/autoload.php'; // 在循环内替换解析部分 $wkt = $res['geo']; $geometryObj = geoPHP::load($wkt, 'wkt'); // 直接获取符合规范的geometry数组结构 $geometry = json_decode($geometryObj->out('json'), true);
这样不管是哪种几何类型,都能自动转换成符合GeoJSON规范的对象。
内容的提问来源于stack exchange,提问作者Bill Chappell
相关产品推荐
相关产品推荐

