经纬志
首页 / 实战手册 / 数据加载

MultiPolygon 少包一层数组,渲染直接报 invalid geometry

先看结论

后端拼的 GeoJSON 在 QGIS 里打不开,前端有时报错、有时什么都不画。

最后验证 2026-11-03 · 多技术栈 · 更新 2026-10-29 · 引用本文

现象

接口返回的要素 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 层结构,被判定为非法。

排查过程

  1. 打印 geometry.coordinates,逐层看长度:第一层是数组、第二层是数组还是数字。
  2. 用递归深度函数数层数,与上表比对。
  3. 检查服务端是否手工拼装了几何对象,而不是交给 PostGIS 的 ST_AsGeoJSON。
  4. 用 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.js7.x严格校验层数,抛异常
Mapbox GL JS2.15 / 3.x非法几何静默丢弃
Leaflet1.9.x不报错,直接不渲染
PostGIS3.4ST_Multi 保证结构合法
引用本文

经纬志(2026)。《MultiPolygon 少包一层数组,渲染直接报 invalid geometry》。https://www.jingweizhi.com/cookbook/geojson-multipolygon-depth.html(访问日期 2026-11-03)。