用 geojson 包而非 encoding/json:它能正确处理 geometrycollection、multipolygon 嵌套、废弃 crs 字段及任意 properties 类型,避免 panic 或丢失高程;推荐使用 unmarshalfeaturecollection() 入口,并通过递归 extractcoords 提取坐标,注意 bom 和坐标顺序校验。

GeoJSON 解析用 geojson 还是 encoding/json?
直接上结论:别自己写结构体硬解,用 geojson 包(如 github.com/paulmach/go.geojson)——它能正确处理 GeometryCollection、MultiPolygon 坐标嵌套、crs 字段(哪怕已废弃)、以及 properties 的任意键值类型。自己用 encoding/json + struct 解,大概率在遇到 type 为 FeatureCollection 且含混合 geometry 类型时 panic,或漏掉 coordinates 里的第三维高程值。
-
geojson.UnmarshalFeatureCollection()是最稳的入口,它自动识别features数组并归一化 geometry - 如果只关心坐标,别碰
feature.Properties的 map[string]interface{},直接取feature.Geometry后调geometry.Coordinates() - 注意:该包默认把
Point坐标当作[]float64,但LineString返回[][]float64,Polygon是[][][]float64——维度差异必须按 type 分支处理,不能统一 for range
提取所有坐标的通用函数怎么写?
核心是递归展开 geometry,不是靠 if-else 列全类型。GeoJSON 规范允许 GeometryCollection 套 MultiPoint 套 Point,硬编码会漏。
func extractCoords(g geojson.Geometry) [][]float64 {
switch g := g.(type) {
case *geojson.Point:
return [][]float64{g.Coordinates()}
case *geojson.LineString:
return g.Coordinates()
case *geojson.Polygon:
var coords [][]float64
for _, ring := range g.Coordinates() {
coords = append(coords, ring...)
}
return coords
case *geojson.MultiPoint, *geojson.MultiLineString, *geojson.MultiPolygon:
return g.Coordinates()
case *geojson.GeometryCollection:
var all [][]float64
for _, geom := range g.Geometries {
all = append(all, extractCoords(geom)...)
}
return all
default:
return nil
}
}-
g.Coordinates()返回的已经是[][]float64或更深层切片,别再手动json.Unmarshal -
GeometryCollection的Geometries字段是[]geojson.Geometry接口,可直接递归 - 如果原始 GeoJSON 有
z值(如[116.4, 39.9, 50.2]),Coordinates()会原样保留,无需额外解析
读文件时 os.Open 报 invalid character 怎么办?
这基本等于文件开头有 BOM(Byte Order Mark)或用了 Windows 换行符混了不可见控制字符。GeoJSON 是 UTF-8 文本,但 Go 的 json 包对 BOM 零容忍,一碰到 \uFEFF 就报 invalid character ''。
-
先用
head -c 10 file.geojson | hexdump -C看前几个字节,确认是否有ef bb bf立即学习“go语言免费学习笔记(深入)”;
读文件时加一层 BOM 跳过逻辑:
bytes.TrimPrefix(data, []byte("\xef\xbb\xbf"))
塑料卡板销售统计管理系统下载塑料卡板销售统计管理系统是一款对商品销售情况进行统一管理的系统。 程序特点1,简单,方便,网络操作,不受单台电脑文件保存限制2,纸质与数据库客户数据保存,查询变得更为方便3,免去久远的历史单据与数据查询烦恼4,方便的数据统计与自动核算功能5,丰富的销售数据录入与管理6, 销售清单(送货单)打印功能,支持条型码.7, 销售业绩提成统计功能8, 收款与未收款分开统计功能 后台地址:admin/logi
更稳妥的是用
bufio.NewReader+ReadBytes逐行读,跳过空行和注释行(虽然 GeoJSON 不该有注释,但某些导出工具会塞)别用
ioutil.ReadFile(已弃用),改用os.ReadFile如果文件来自前端
fetch或用户上传,务必检查Content-Type是否为application/geo+json,否则可能被当 text/html 解析出乱码
坐标顺序是 [lng, lat] 还是 [lat, lng]?
GeoJSON 规范强制要求 [longitude, latitude],即 [x, y],和地图 API(如 Leaflet、Mapbox)一致。但国内部分 GIS 工具(如某些 ArcGIS 导出、百度地图 SDK)会反着存,导致点飘到大西洋。
- 不要假设顺序,先看
feature.Geometry.BoundingBox():如果minX在 73–135 之间、minY在 18–54 之间,大概率是正常中国范围;反之若minX在 18–54,则说明坐标被 swap 了 - 简单检测法:取第一个
Point的Coordinates(),判断abs(coord[0]) > 180 || abs(coord[1]) > 90—— 若成立,十有八九是 lat/lng 错位 - 修复只需交换:
coords[0], coords[1] = coords[1], coords[0],但必须全局统一处理,不能只修一个 feature
GeoJSON 的 geometry 嵌套层级和坐标维度变化比想象中多,靠“试一下”容易漏边角 case。真正省事的方式是:用标准库解析结构,用 geojson 包做类型分发,坐标提取逻辑只写一次递归,其他交给它。









