GeoJSON到底是什么格式?一文搞懂GIS数据转换与应用(附:WebGIS开发实战源码)

编程与开发
Dr.GIS
wowwwai GIS研习社 · 工具流程与项目排障

《GeoJSON到底是什么格式?一文搞懂GIS数据转换与应用(附:WebGIS开发实战源码)》这篇文章,主要解决一个很常见的问题:拿到一个 GeoJSON 文件后,GIS 初学者、WebGIS 开发者和数据分析人员应该如何判断它是否正确、如何与 Shapefile 等格式互转,以及如何在网页地图中加载使用。

GeoJSON 是 WebGIS 项目里非常常见的矢量数据格式。它看起来像普通 JSON,但里面有明确的地理空间结构:点、线、面、属性字段和坐标。理解 GeoJSON 格式,不只是为了“能打开文件”,更重要的是避免坐标系错误、文件过大、面要素不闭合、中文乱码和前端加载卡顿等问题。

GeoJSON格式与GeoJSON数据转换WebGIS应用流程图
GeoJSON 常见工作流:从 GIS 数据源转换、检查,到 WebGIS 前端加载展示。

引言:为什么 WebGIS 项目经常使用 GeoJSON

如果你做过 Leaflet、OpenLayers、Mapbox GL 或 Cesium 项目,大概率会遇到 GeoJSON。它的优势很直接:文本格式、结构清晰、浏览器容易解析、适合表达中小规模矢量数据。

在 GIS 软件中,GeoJSON 常用于以下场景:

  • 把 QGIS 或 ArcGIS Pro 中的矢量图层导出给前端使用。
  • 把接口返回的空间数据直接显示到 WebGIS 地图上。
  • 保存简单的点、线、面标注数据。
  • 作为 Python、PostGIS、GDAL 等工具之间的数据交换格式。
  • 用于调试空间数据,因为它可以直接用文本编辑器查看。

但 GeoJSON 也不是万能格式。它不适合直接承载超大数据量,不适合保存复杂制图样式,也不适合作为空间数据库的替代品。正确的做法是:理解它的结构,用它完成合适的任务。

背景:GeoJSON 到底是什么格式

GeoJSON 是一种基于 JSON 的地理空间数据交换格式。JSON 是一种常见的数据文本格式,而 GeoJSON 在 JSON 的基础上规定了空间对象的写法。

一个标准 GeoJSON 文件通常包含三部分:

  • type:说明对象类型,例如 FeatureCollection、Feature、Point、LineString、Polygon。
  • geometry:保存几何信息,也就是坐标和几何类型。
  • properties:保存属性字段,例如名称、编号、类型、人口、面积等。

最常见的 GeoJSON 顶层结构是 FeatureCollection,意思是“要素集合”。一个文件里可以有多个 Feature,每个 Feature 对应 GIS 中的一条要素记录。

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "name": "样例点",
        "category": "A"
      },
      "geometry": {
        "type": "Point",
        "coordinates": [116.3913, 39.9075]
      }
    }
  ]
}

上面这个例子表示一个点要素。coordinates 中的坐标顺序是经度、纬度,也就是 [longitude, latitude]。这是很多初学者出错的地方:不要把它写成纬度、经度。

原理:GeoJSON 的几何类型和坐标规则

GeoJSON 支持多种几何类型。理解这些类型,是进行 GeoJSON 数据转换和 WebGIS 加载的基础。

GeoJSON 类型 对应 GIS 要素 坐标结构说明
Point 一个坐标,例如 [116.39, 39.90]
MultiPoint 多点 多个点坐标组成的数组
LineString 线 两个或多个坐标点组成一条线
MultiLineString 多线 多条 LineString 的集合
Polygon 由闭合线环组成,首尾坐标必须一致
MultiPolygon 多面 多个 Polygon 的集合
GeometryCollection 几何集合 不同几何类型的组合

GeoJSON 最需要注意的是坐标系。按照常见规范,GeoJSON 通常使用 WGS84 地理坐标系,也就是 EPSG:4326,经纬度单位为度。虽然一些工具也能读写其他坐标系的 GeoJSON,但在 WebGIS 前端开发中,最稳妥的做法是把数据转换到 EPSG:4326。

如果你的数据来自 CGCS2000、高斯克吕格投影、Web Mercator 或地方坐标系,直接导出 GeoJSON 后可能会出现位置偏移、图层飞到海里、要素完全不显示等问题。原因不是 GeoJSON 本身坏了,而是坐标系没有正确处理。

步骤:如何把 Shapefile 转换为 GeoJSON

下面以 QGIS 为例,演示一个常见的 GeoJSON 数据转换流程。这个流程适合把 Shapefile、GeoPackage、PostGIS 查询结果等矢量数据导出为 GeoJSON。

步骤一:在 QGIS 中加载原始数据

  1. 打开 QGIS。
  2. 将 Shapefile 的 .shp 文件拖入地图窗口。
  3. 右键图层,选择属性,查看源数据坐标参考系统。
  4. 确认图层是否能正确显示在底图或已知行政边界上。

在转换前先确认原始数据位置是否正确。不要在数据已经偏移的情况下继续导出 GeoJSON,否则后续 WebGIS 中仍然会偏移。

步骤二:必要时先重投影到 EPSG:4326

如果原始数据不是 WGS84,经常建议先执行重投影。操作方法如下:

  1. 右键图层,选择导出。
  2. 选择“另存为”。
  3. 格式先可选择 GeoPackage 或直接选择 GeoJSON。
  4. 坐标参考系统选择 EPSG:4326 – WGS 84。
  5. 设置文件路径并保存。

这里要区分两个概念:设置图层坐标系和重投影。设置图层坐标系只是告诉软件“这个数据原本是什么坐标系”;重投影才是真正把坐标值转换到新的坐标系统。

步骤三:导出为 GeoJSON

  1. 右键目标图层。
  2. 选择“导出”。
  3. 选择“另存为”。
  4. 格式选择 GeoJSON。
  5. 文件名建议使用英文、数字和短横线,例如 roads-wgs84.geojson。
  6. 编码选择 UTF-8。
  7. 坐标参考系统选择 EPSG:4326。
  8. 点击确定导出。

导出完成后,可以用文本编辑器打开 GeoJSON 文件,检查 type、features、geometry 和 properties 是否存在。也可以重新把 GeoJSON 拖入 QGIS,检查空间位置和属性字段是否正常。

步骤:使用 GDAL 命令行转换 GeoJSON

如果你需要批量转换,GDAL 的 ogr2ogr 更适合。下面是把 Shapefile 转为 GeoJSON 的常用命令:

ogr2ogr -f GeoJSON output.geojson input.shp -t_srs EPSG:4326

参数含义如下:

  • -f GeoJSON:指定输出格式为 GeoJSON。
  • output.geojson:输出文件。
  • input.shp:输入 Shapefile。
  • -t_srs EPSG:4326:把输出结果转换为 WGS84 坐标系。

如果原始数据缺少坐标系信息,但你确定它的真实坐标系,可以使用 -s_srs 指定源坐标系:

ogr2ogr -f GeoJSON output.geojson input.shp -s_srs EPSG:4547 -t_srs EPSG:4326

这里的 EPSG:4547 只是示例。实际项目中必须根据数据来源确认正确 EPSG 编码,不能随意猜测。

步骤:GeoJSON 在 WebGIS 中如何加载

GeoJSON 的重要应用场景是前端地图加载。下面给出一个 Leaflet 的最小实战示例,用于加载本地或服务器上的 GeoJSON 文件。

Leaflet 加载 GeoJSON 示例

<div id="map" style="height: 500px;"></div>

<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css">
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>

<script>
  const map = L.map('map').setView([39.9075, 116.3913], 10);

  L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
    maxZoom: 19
  }).addTo(map);

  fetch('/data/sample.geojson')
    .then(response => response.json())
    .then(data => {
      const geojsonLayer = L.geoJSON(data, {
        style: function(feature) {
          return {
            color: '#0066cc',
            weight: 2,
            fillColor: '#66ccff',
            fillOpacity: 0.4
          };
        },
        onEachFeature: function(feature, layer) {
          if (feature.properties) {
            const name = feature.properties.name || '未命名要素';
            layer.bindPopup(name);
          }
        }
      }).addTo(map);

      map.fitBounds(geojsonLayer.getBounds());
    });
</script>

这个示例做了三件事:创建地图、请求 GeoJSON 文件、把 GeoJSON 渲染成地图图层。fitBounds 用于自动缩放到数据范围,适合调试数据是否加载成功。

OpenLayers 加载 GeoJSON 示例

如果你的项目使用 OpenLayers,可以参考下面的写法:

import Map from 'ol/Map';
import View from 'ol/View';
import GeoJSON from 'ol/format/GeoJSON';
import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
import TileLayer from 'ol/layer/Tile';
import OSM from 'ol/source/OSM';
import {fromLonLat} from 'ol/proj';

const vectorSource = new VectorSource({
  url: '/data/sample.geojson',
  format: new GeoJSON()
});

const vectorLayer = new VectorLayer({
  source: vectorSource
});

const map = new Map({
  target: 'map',
  layers: [
    new TileLayer({
      source: new OSM()
    }),
    vectorLayer
  ],
  view: new View({
    center: fromLonLat([116.3913, 39.9075]),
    zoom: 10
  })
});

OpenLayers 内部通常使用 Web Mercator 投影显示地图,但 GeoJSON 数据常以 EPSG:4326 存储。使用 ol/format/GeoJSON 时,常见项目会结合 dataProjection 和 featureProjection 明确指定投影,避免坐标显示异常。

const vectorSource = new VectorSource({
  url: '/data/sample.geojson',
  format: new GeoJSON({
    dataProjection: 'EPSG:4326',
    featureProjection: 'EPSG:3857'
  })
});

常见坑:GeoJSON 数据转换与应用最容易出错的地方

1. 坐标顺序写反

GeoJSON 坐标通常是 [经度, 纬度],不是 [纬度, 经度]。例如北京附近点位应写为 [116.39, 39.90]。如果写成 [39.90, 116.39],地图位置会完全错误。

2. 坐标系没有转换

很多工程数据是投影坐标,坐标值可能是几百万米。如果直接当作经纬度写进 GeoJSON,WebGIS 地图肯定无法正常显示。导出前应确认是否需要转换到 EPSG:4326。

3. Polygon 面要素没有闭合

GeoJSON 的 Polygon 线环首尾坐标必须一致。错误示例是第一个点和最后一个点不同,这会导致部分工具无法正确识别面。

{
  "type": "Polygon",
  "coordinates": [
    [
      [116.1, 39.1],
      [116.2, 39.1],
      [116.2, 39.2],
      [116.1, 39.2],
      [116.1, 39.1]
    ]
  ]
}

4. 文件太大导致 WebGIS 加载卡顿

GeoJSON 是文本格式,浏览器需要下载、解析和渲染全部内容。数据量较大时,页面会明显变慢。对于行政区边界、道路网、大量地块等数据,不建议直接加载原始 GeoJSON。

可选优化方法包括:

  • 在 QGIS 中进行几何简化。
  • 按行政区或瓦片范围切分 GeoJSON。
  • 转换为矢量瓦片。
  • 使用 PostGIS 后端按范围查询。
  • 只返回当前地图视野内的数据。

5. 属性字段类型混乱

GeoJSON 的 properties 很灵活,但过度灵活也容易带来问题。例如同一个字段,有些要素是数字,有些要素是字符串,前端样式分类和统计时就容易出错。导出前建议统一字段类型。

6. 中文字段或中文路径引发问题

现代工具通常支持 UTF-8,但仍建议文件名、服务路径、字段名尽量使用英文。属性值可以保留中文,编码选择 UTF-8。

方法比较:GeoJSON、Shapefile、GeoPackage、PostGIS 怎么选

格式或工具 适合场景 主要优点 主要限制
GeoJSON WebGIS 前端展示、接口返回、中小数据交换 文本可读、浏览器友好、结构简单 大数据加载慢,不保存复杂样式
Shapefile 传统 GIS 数据交换、桌面软件兼容 兼容性强,很多软件支持 多文件组成,字段名长度受限,编码问题常见
GeoPackage 桌面 GIS 项目、移动端数据包、较规范的数据存储 单文件,可存多个图层,支持空间索引 前端浏览器不能像 GeoJSON 那样直接加载
PostGIS 空间数据库、多人协作、大数据查询 支持空间索引、SQL 查询、并发访问 需要数据库部署和后端接口
矢量瓦片 大规模 WebGIS 可视化 加载快,适合多级缩放 制作和服务发布流程更复杂

简单判断:如果是小规模数据展示,GeoJSON 很方便;如果是长期存储和编辑,优先考虑 GeoPackage 或 PostGIS;如果是大规模在线地图展示,优先考虑矢量瓦片或后端按范围服务。

检查清单:发布 GeoJSON 前建议逐项确认

  • GeoJSON 文件能否被 QGIS 正常打开。
  • 图层位置是否与底图或已知边界重合。
  • 坐标是否为经纬度,常见范围是否合理。
  • 坐标顺序是否为 [经度, 纬度]。
  • 面要素是否闭合,几何是否有效。
  • 属性字段是否完整,字段类型是否统一。
  • 文件编码是否为 UTF-8。
  • 文件大小是否适合浏览器直接加载。
  • 前端请求路径是否正确,服务器是否允许访问。
  • Leaflet 或 OpenLayers 中是否正确设置投影和样式。

如果 GeoJSON 在 WebGIS 中不显示,建议先不要急着改代码。先把文件拖到 QGIS 中检查,再用浏览器开发者工具查看网络请求是否成功,最后检查坐标系和坐标范围。

FAQ:GeoJSON 常见问题

GeoJSON 和 JSON 有什么区别?

JSON 是通用数据格式,GeoJSON 是一种专门表达地理空间数据的 JSON 规范。GeoJSON 规定了 Feature、FeatureCollection、geometry、coordinates、properties 等结构,用来表达 GIS 要素。

GeoJSON 必须是 EPSG:4326 吗?

实际工具中可能存在其他坐标系的 GeoJSON,但在 WebGIS 数据交换中,通常建议使用 EPSG:4326。这样最容易与 Leaflet、OpenLayers、Web 地图底图和接口数据配合。

为什么我的 GeoJSON 加载后位置偏移?

常见原因有三个:源数据坐标系判断错误、没有执行真正的重投影、坐标顺序写反。建议先在 QGIS 中检查原始数据和导出数据的位置,再检查 WebGIS 前端投影设置。

GeoJSON 文件很大怎么办?

可以先做几何简化、字段精简和数据切分。如果数据仍然很大,建议改用矢量瓦片、PostGIS 后端接口或按地图视野动态查询,不要一次性把完整 GeoJSON 加载到浏览器。

GeoJSON 能保存图层样式吗?

GeoJSON 主要保存几何和属性,不是完整的制图工程文件。可以在 properties 中保存分类字段或颜色字段,但最终样式通常由 QGIS、Leaflet、OpenLayers 或其他客户端代码来定义。

Shapefile 转 GeoJSON 后字段丢失怎么办?

先检查 Shapefile 原始字段名和编码。Shapefile 对字段名长度和类型有一些限制,转换时也可能受到编码影响。建议在转换前整理字段名,使用 UTF-8,并在 QGIS 中核对属性表。

GeoJSON 适合做数据存档吗?

不太建议把 GeoJSON 作为大型项目的长期主存储格式。它适合作为交换格式和前端展示格式。长期管理空间数据,建议使用 GeoPackage、PostGIS 或项目规定的数据库方案。

结论:把 GeoJSON 当作 WebGIS 数据交换格式来理解

GeoJSON 的核心价值在于简单、开放、易读、适合 WebGIS。理解 GeoJSON 格式后,你就能更稳定地完成 GIS 数据转换、前端地图加载和空间接口调试。

实际项目中建议记住三点:第一,导出前确认坐标系;第二,WebGIS 中检查坐标顺序和投影设置;第三,大数据不要直接用原始 GeoJSON 硬加载。只要把这三点处理好,GeoJSON 就是 GIS 数据转换与 WebGIS 开发中非常实用的一环。