MultiPolygon 少包一层数组,渲染直接报 invalid geometry
后端拼的 GeoJSON 在 QGIS 里打不开,前端有时报错、有时什么都不画。
现象
接口返回的要素 geometry.type 是 MultiPolygon,
控制台报 Error: Invalid MultiPolygon coordinates: coordinates must be an array of Polygon coordinate arrays。
Leaflet 不报错,但该要素完全不渲染。
在 QGIS 里用「添加矢量图层」打开同一文件,提示
GeoJSON 无效:无法解析几何。
原因
GeoJSON 对每种几何类型的嵌套层数有严格定义:
| 类型 | coordinates 结构 | 层数 |
|---|---|---|
| Point | [lng, lat] | 1 |
| LineString | [[lng, lat], ...] | 2 |
| Polygon | [[[lng, lat], ...]](环的数组) | 3 |
| MultiPolygon | [[[[lng, lat], ...]]](面的数组) | 4 |
后端如果用 ST_AsGeoJSON 处理单个面再手工改 type 为 MultiPolygon,
就会漏掉外面那层,得到 3 层结构,被判定为非法。
排查过程
- 打印
geometry.coordinates,逐层看长度:第一层是数组、第二层是数组还是数字。 - 用递归深度函数数层数,与上表比对。
- 检查服务端是否手工拼装了几何对象,而不是交给 PostGIS 的
ST_AsGeoJSON。 - 用
turf.cleanCoords或 QGIS 打开验证,非法几何会被直接拒绝。
function depth(a) {
return Array.isArray(a) ? 1 + Math.max(...a.map(depth)) : 0;
}
depth(fc.features[0].geometry.coordinates); // 3 -> 应为 4
// 直接看前两层
console.log(fc.features[0].geometry.coordinates[0]);
// 错误:[ [116.1,39.8], [116.2,39.8], ... ]
// 正确:[ [ [116.1,39.8], [116.2,39.8], ... ] ]
解决方案
不要手工改 type。要区分单个面和多个面,用 ST_Multi 让 PostGIS 产出正确结构。
-- 正确:交给 PostGIS 生成 MultiPolygon
SELECT jsonb_build_object(
'type', 'Feature',
'properties', jsonb_build_object('name', name),
'geometry', ST_AsGeoJSON(ST_Multi(geom), 15)::jsonb
)
FROM districts;
-- 若只有一个面,ST_Multi 也会生成合法的 MultiPolygon
前端收到已经错位的结构时,补一层数组即可,但要先确认里面确实是「面」而不是「环」。
function fixMultiPolygon(geom) {
if (geom.type !== 'MultiPolygon') return geom;
if (depth(geom.coordinates) === 4) return geom;
return { ...geom, coordinates: [geom.coordinates] }; // 包一层
}
fc.features.forEach(f => { f.geometry = fixMultiPolygon(f.geometry); });
turf.area(fc.features[0]);
// 北京市某区面积应在 1.3e8 平方米量级
验证
修复后 depth 返回 4,turf.area 能算出合理面积,
地图上每个要素正常着色,QGIS 可打开且无拓扑报错。
const g = fc.features[0].geometry;
console.assert(depth(g.coordinates) === 4, '仍缺一层');
console.assert(turf.area(fc.features[0]) > 1e7, '面积量级不对');
适用版本
| 库 | 版本 | 校验严格度 |
|---|---|---|
| turf.js | 7.x | 严格校验层数,抛异常 |
| Mapbox GL JS | 2.15 / 3.x | 非法几何静默丢弃 |
| Leaflet | 1.9.x | 不报错,直接不渲染 |
| PostGIS | 3.4 | ST_Multi 保证结构合法 |
经纬志(2026)。《MultiPolygon 少包一层数组,渲染直接报 invalid geometry》。https://www.jingweizhi.com/cookbook/geojson-multipolygon-depth.html(访问日期 2026-11-03)。