GeoJSON到底是什么格式?一文搞懂GIS数据转换与应用(附:WebGIS开发实战源码)
《GeoJSON到底是什么格式?一文搞懂GIS数据转换与应用(附:WebGIS开发实战源码)》这篇文章,主要解决一个很常见的问题:拿到一个 GeoJSON 文件后,GIS 初学者、WebGIS 开发者和数据分析人员应该如何判断它是否正确、如何与 Shapefile 等格式互转,以及如何在网页地图中加载使用。
GeoJSON 是 WebGIS 项目里非常常见的矢量数据格式。它看起来像普通 JSON,但里面有明确的地理空间结构:点、线、面、属性字段和坐标。理解 GeoJSON 格式,不只是为了“能打开文件”,更重要的是避免坐标系错误、文件过大、面要素不闭合、中文乱码和前端加载卡顿等问题。

引言:为什么 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 中加载原始数据
- 打开 QGIS。
- 将 Shapefile 的 .shp 文件拖入地图窗口。
- 右键图层,选择属性,查看源数据坐标参考系统。
- 确认图层是否能正确显示在底图或已知行政边界上。
在转换前先确认原始数据位置是否正确。不要在数据已经偏移的情况下继续导出 GeoJSON,否则后续 WebGIS 中仍然会偏移。
步骤二:必要时先重投影到 EPSG:4326
如果原始数据不是 WGS84,经常建议先执行重投影。操作方法如下:
- 右键图层,选择导出。
- 选择“另存为”。
- 格式先可选择 GeoPackage 或直接选择 GeoJSON。
- 坐标参考系统选择 EPSG:4326 – WGS 84。
- 设置文件路径并保存。
这里要区分两个概念:设置图层坐标系和重投影。设置图层坐标系只是告诉软件“这个数据原本是什么坐标系”;重投影才是真正把坐标值转换到新的坐标系统。
步骤三:导出为 GeoJSON
- 右键目标图层。
- 选择“导出”。
- 选择“另存为”。
- 格式选择 GeoJSON。
- 文件名建议使用英文、数字和短横线,例如 roads-wgs84.geojson。
- 编码选择 UTF-8。
- 坐标参考系统选择 EPSG:4326。
- 点击确定导出。
导出完成后,可以用文本编辑器打开 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 开发中非常实用的一环。