Geopandas导出GeoJSON?中文乱码咋解?

GIS基础理论
Dr.GIS
wowwwai GIS研习社 · 工具流程与项目排障

遇到“Geopandas导出GeoJSON?中文乱码咋解?”这个问题,通常不是 GeoPandas 本身“不能写中文”,而是数据源编码、字段内容类型、导出参数、查看软件或 WebGIS 前端解码方式之间没有对齐。本文用一个可复现的排查流程,帮你把 GeoPandas 导出 GeoJSON 中文乱码的问题定位清楚,并给出稳定的处理写法。

引言:GeoPandas导出GeoJSON中文乱码最常见的场景

在 GIS 项目里,很多同学会先用 Shapefile、CSV、Excel 或 PostGIS 数据做处理,再用 GeoPandas 导出 GeoJSON 给 QGIS、Leaflet、OpenLayers 或 Cesium 使用。问题往往出现在最后一步:属性表里的中文地名、道路名、行政区名称变成了乱码。

典型表现包括:

  • GeoJSON 文件打开后,中文显示为 北京 这类字符。
  • QGIS 打开 GeoJSON 中文正常,但浏览器页面显示乱码。
  • Python 里打印中文正常,导出 GeoJSON 后用文本编辑器查看乱码。
  • 从 Shapefile 读取时已经乱码,后面怎么导出 GeoJSON 都不对。

处理这类问题,要先判断乱码发生在读取阶段写出阶段,还是展示阶段。不要一上来就反复改 GeoJSON 文件后缀或换浏览器,这样很容易把问题越修越乱。

GeoPandas导出GeoJSON中文乱码排查流程 Geopandas导出GeoJSON中文乱码
GeoPandas 导出 GeoJSON 中文乱码通常要从源数据读取、文件写出和前端展示三个环节逐一排查。

背景:为什么 GeoJSON 应该优先使用 UTF-8

GeoJSON 是一种基于 JSON 的空间数据格式,常用于 WebGIS 数据交换。按照实际使用习惯和 Web 生态兼容性,GeoJSON 文件应优先保存为 UTF-8 编码。UTF-8 能稳定表达中文、英文、数字和各种符号,也是浏览器、JavaScript、QGIS、PostGIS 等工具链里最通用的选择。

GeoPandas 导出 GeoJSON 时,底层通常通过 Fiona 或 Pyogrio 等 I/O 引擎调用 GDAL/OGR 完成写出。现代版本对 UTF-8 支持比较好,但如果你的源数据本身不是 UTF-8,或者读取时编码判断错误,导出后的 GeoJSON 仍然会带着错误字符。

所以,GeoPandas 导出 GeoJSON 中文乱码的本质通常是:读取进 GeoDataFrame 的字符串已经不是正确中文,或者文件输出后被错误编码方式打开。

原理:先判断乱码发生在哪一步

排查 GeoPandas 导出 GeoJSON 中文乱码,可以把流程拆成三段:

  1. 源数据读取:Shapefile、CSV、Excel、数据库里的中文是否被 GeoPandas 正确读入。
  2. GeoJSON 写出:GeoDataFrame 写成 GeoJSON 时是否使用了合适的驱动和编码。
  3. 结果查看:QGIS、浏览器、文本编辑器或 WebGIS 前端是否按 UTF-8 读取。

最简单的判断方法是在导出之前先打印属性字段:

import geopandas as gpd

gdf = gpd.read_file("data/input.shp")
print(gdf.head())
print(gdf["name"].head())

如果这里已经显示乱码,说明问题发生在读取阶段。此时直接导出 GeoJSON 没有意义,因为 GeoDataFrame 里的中文已经错了。

如果这里中文正常,而导出的 GeoJSON 在浏览器或前端显示乱码,问题多半在写出或展示阶段。这时要重点检查文件编码、HTTP 响应头和前端读取方式。

步骤:GeoPandas导出GeoJSON中文乱码的推荐处理流程

步骤一:确认 Python 环境和 GeoPandas 能正常读取数据

先用最小代码读取数据,并查看中文字段是否正常:

import geopandas as gpd

input_path = "data/input.shp"
gdf = gpd.read_file(input_path)

print(gdf.crs)
print(gdf.columns)
print(gdf.head())
print(gdf["名称"].head())

如果输出窗口里中文字段显示正常,说明 GeoPandas 读入阶段基本没问题。下一步可以检查导出。

如果中文已经乱码,先不要写 GeoJSON。要回到源数据编码。尤其是 Shapefile,它的属性表存储在 DBF 文件里,编码经常依赖 .cpg 文件或软件默认设置。

步骤二:Shapefile 中文乱码时指定 encoding 读取

如果源数据是 Shapefile,并且中文字段在读取后乱码,可以尝试指定编码:

import geopandas as gpd

gdf = gpd.read_file("data/input.shp", encoding="utf-8")
print(gdf["名称"].head())

如果 UTF-8 不对,国内历史数据常见编码还包括 GBK、GB18030:

import geopandas as gpd

gdf = gpd.read_file("data/input.shp", encoding="gbk")
print(gdf["名称"].head())

gdf = gpd.read_file("data/input.shp", encoding="gb18030")
print(gdf["名称"].head())

判断标准很简单:哪个编码读出来的中文是正确的,就用哪个。不要同时乱改多个参数。

如果数据目录里有 .cpg 文件,也可以打开检查里面写的是不是 UTF-8、GBK 或其他编码。Shapefile 中文乱码很大一部分就来自 .cpg 缺失或内容不准确。

步骤三:用 UTF-8 导出 GeoJSON

当 GeoDataFrame 里的中文已经正常后,再导出 GeoJSON:

import geopandas as gpd

gdf = gpd.read_file("data/input.shp", encoding="gbk")

output_path = "output/result.geojson"
gdf.to_file(output_path, driver="GeoJSON", encoding="utf-8")

在多数现代 GeoPandas 环境中,即使不显式写 encoding="utf-8",GeoJSON 也通常会以 UTF-8 写出。但在教程和团队脚本里,建议把编码写清楚,便于别人理解你的意图。

步骤四:如果来自 CSV,读取时就要指定 encoding

如果源数据是 CSV,并且你先用 pandas 读取再转为 GeoDataFrame,也要在读取 CSV 时处理编码:

import pandas as pd
import geopandas as gpd
from shapely.geometry import Point

df = pd.read_csv("data/points.csv", encoding="gbk")

geometry = [Point(xy) for xy in zip(df["lon"], df["lat"])]
gdf = gpd.GeoDataFrame(df, geometry=geometry, crs="EPSG:4326")

gdf.to_file("output/points.geojson", driver="GeoJSON", encoding="utf-8")

如果 CSV 是 Excel 另存出来的,在中文 Windows 环境下很可能是 GBK 或带 BOM 的 UTF-8。可以分别尝试:

df = pd.read_csv("data/points.csv", encoding="utf-8")
df = pd.read_csv("data/points.csv", encoding="utf-8-sig")
df = pd.read_csv("data/points.csv", encoding="gbk")

utf-8-sig 常用于处理带 BOM 的 UTF-8 文件。BOM 是文件开头用于标识编码的字节标记,有些软件会生成,有些工具处理不好。

步骤五:用文本方式验证 GeoJSON 是否是 UTF-8

导出后,可以用 Python 直接按 UTF-8 打开文件验证:

with open("output/result.geojson", "r", encoding="utf-8") as f:
    text = f.read(500)

print(text)

如果这里能正确看到中文,说明 GeoJSON 文件本身大概率没问题。若前端仍然乱码,就要检查 Web 服务响应头或页面编码。

步骤六:WebGIS 前端加载 GeoJSON 时检查 HTTP 编码

如果 GeoJSON 是通过服务器提供给 Leaflet 或 OpenLayers,建议让 HTTP 响应头明确包含 UTF-8:

Content-Type: application/geo+json; charset=utf-8

或者至少:

Content-Type: application/json; charset=utf-8

前端页面本身也应使用 UTF-8:

<meta charset="utf-8">

如果 GeoJSON 文件本身是 UTF-8,但服务器按其他编码发送,浏览器端就可能出现中文乱码。此时问题不在 GeoPandas,而在部署和服务配置。

常见坑:GeoPandas导出GeoJSON中文乱码别只改最后一步

坑一:源 Shapefile 已经读错

很多人以为乱码是在 GeoPandas 导出 GeoJSON 时产生的,但实际是在读取 Shapefile 时就已经错了。只要 print(gdf.head()) 里是乱码,后续导出必然也是乱码。

坑二:用文本编辑器误判编码

有些文本编辑器会自动猜测编码,猜错后会显示乱码。建议至少用两个工具交叉验证,例如 Python 按 UTF-8 读取、QGIS 打开、VS Code 右下角查看编码。

坑三:把坐标系问题和中文乱码混在一起

GeoJSON 中文乱码和坐标偏移不是一类问题。中文乱码主要是字符编码问题;地图位置不对通常是 CRS,也就是坐标参考系统问题。不要因为中文乱码就去改 EPSG 代码。

坑四:字段名是中文时忽略兼容性

GeoJSON 可以保存中文字段名,但在一些前端框架、数据库入库流程或团队规范里,中文字段名可能带来额外处理成本。建议重要项目中使用英文或拼音字段名,中文放在字段值里。

# 推荐:字段名稳定,字段值可为中文
name = "天安门"
district = "东城区"

# 不太推荐:大量中文字段名在跨系统流转时更容易出兼容问题
名称 = "天安门"
所在区 = "东城区"

坑五:GeoJSON 文件太大导致前端误以为是乱码问题

如果 GeoJSON 很大,浏览器加载慢、页面卡顿或请求中断,有时会被误判为乱码。此时要看浏览器开发者工具里的 Network 面板,确认响应是否完整、状态码是否正常、Content-Type 是否正确。

方法比较:几种修复 GeoJSON 中文乱码方案怎么选

方法 适用场景 优点 注意事项
读取时指定 encoding Shapefile、CSV 读入后中文已经乱码 从源头修复,最可靠 要先判断原始数据到底是 UTF-8、GBK 还是 GB18030
导出时指定 encoding=”utf-8″ GeoDataFrame 中中文正常,需要稳定输出 GeoJSON 脚本意图清楚,适合团队复用 如果读入阶段已经乱码,该方法不能恢复中文
检查 .cpg 文件 Shapefile 中文字段经常乱码 能帮助 GIS 软件识别 DBF 编码 .cpg 写错时反而会误导软件
修正 Web 服务器响应头 本地文件正常,浏览器或 WebGIS 显示乱码 解决前端部署问题 需要检查 Nginx、Apache、对象存储或后端接口配置
统一字段名规范 数据要进入 WebGIS、数据库或多人协作流程 减少跨系统兼容问题 字段值仍然可以保留中文

检查清单:快速定位 GeoPandas 导出 GeoJSON 中文乱码

  • 导出前执行 print(gdf.head()),确认 GeoDataFrame 里的中文是否正常。
  • 如果读取 Shapefile 乱码,尝试 encoding="utf-8"encoding="gbk"encoding="gb18030"
  • 检查 Shapefile 同目录下是否有 .cpg 文件,内容是否与实际编码一致。
  • 如果读取 CSV,优先检查 pd.read_csv() 的 encoding 参数。
  • 导出 GeoJSON 时明确使用 driver="GeoJSON"
  • 建议导出时写明 encoding="utf-8",让脚本更可读。
  • 用 Python 按 UTF-8 读取导出的 GeoJSON,确认文件本身是否正常。
  • 如果 WebGIS 显示乱码,检查页面 meta charset 和接口 Content-Type
  • 不要把中文乱码和坐标系错位混为一谈。
  • 项目交付时,建议记录源数据编码、导出脚本和目标 GeoJSON 编码。

FAQ:GeoPandas导出GeoJSON中文乱码常见问题

GeoPandas 导出 GeoJSON 一定要写 encoding=”utf-8″ 吗?

不一定。很多环境默认就能正确写出 UTF-8 GeoJSON。但为了脚本清晰和团队可维护,建议显式写上 encoding="utf-8"。如果 GeoDataFrame 里的中文已经乱码,这个参数不能把错误字符自动修复。

为什么 QGIS 打开正常,浏览器显示中文乱码?

这通常说明 GeoJSON 文件本身可能是正常的,但浏览器端没有按 UTF-8 解析。请检查 HTML 页面是否有 <meta charset="utf-8">,以及 GeoJSON 接口响应头是否包含 charset=utf-8

Shapefile 转 GeoJSON 中文乱码应该先改哪里?

先改读取阶段。用 GeoPandas 读取 Shapefile 后马上打印中文字段。如果已经乱码,就通过 gpd.read_file("input.shp", encoding="gbk") 或其他正确编码重新读取。确认中文正常后,再导出 GeoJSON。

GBK 和 GB18030 该选哪个?

如果是国内较早的 Shapefile 或 CSV,GBK 很常见。GB18030 覆盖范围更广,也常用于兼容更多中文字符。实际项目中以读出来是否正确为准,不要凭感觉固定使用某一个编码。

GeoJSON 里中文字段名可以用吗?

可以,但不一定推荐。GeoJSON 支持中文字段名,不过在 WebGIS、数据库、接口文档和团队协作中,英文或拼音字段名更稳定。建议字段名用英文,字段值保留中文。

导出后文件里有反斜杠 u 编码,是乱码吗?

不一定。JSON 中的中文可以直接保存为中文,也可以保存为 Unicode 转义形式,例如 u5317u4eac。这不是乱码,程序解析后仍然是“北京”。真正的乱码通常是字符被错误编码后变成不可读的混乱字符。

结论:先修读取,再修导出,最后查展示

解决 GeoPandas 导出 GeoJSON 中文乱码,关键不是盲目换软件,而是按流程定位:先看 GeoDataFrame 里的中文是否正确,再确认 GeoJSON 是否按 UTF-8 写出,最后检查 QGIS、浏览器或 WebGIS 前端是否按 UTF-8 展示。

最稳妥的实践是:读取 Shapefile 或 CSV 时明确源数据编码,导出 GeoJSON 时使用 UTF-8,并在 Web 服务中声明正确的 Content-Type。这样处理后,GeoPandas 导出 GeoJSON 中文乱码的问题通常都能被快速解决。