最省事的方法是直接用 nlohmann/json 解析 geojson featurecollection,需逐层防御性访问字段、校验结构合法性、避免隐式拷贝,并为坐标系和语义模糊性留出上层干预接口。

用 nlohmann/json 解析 GeoJSON FeatureCollection 最省事
GeoJSON 本质是 JSON,C++ 没原生支持,硬写解析器纯属重复造轮子。直接用 nlohmann/json 是最稳妥的选择——它能自动映射嵌套结构,且对 FeatureCollection 的 type、features、properties 等字段名完全兼容,无需预定义 schema。
注意:必须确保输入 JSON 合法(比如 features 是数组、每个 feature 有 geometry 和 properties),否则 json::parse() 会抛 json::parse_error 异常,不处理会导致崩溃。
- 用
json j = json::parse(json_str)加载字符串;若从文件读,先用std::ifstream读入std::string再 parse - 检查根对象类型:
if (j.at("type") != "FeatureCollection"),避免误传Feature或Geometry -
j.at("features")返回的是json::array_t,遍历时用for (const auto& f : j.at("features")),别用size()+ 下标——nlohmann 的 range-for 更安全
提取单个 Feature 的 geometry 和 properties 要分层访问
GeoJSON 的 Feature 是三层嵌套:feature → geometry → coordinates 和 feature → properties → {任意键值}。nlohmann/json 不做类型推断,所有字段访问都得显式调用 .at() 或 .value(),否则遇到缺失字段会抛异常。
典型错误是直接写 f["geometry"]["coordinates"] ——一旦某个 feature 缺 geometry,程序就 terminate。必须逐层防御性访问。
详细的 Three.js 3D 图形参考,涵盖场景设置、相机、几何体、材质、光照、动画、控制器、加载器、数学工具和调试。
- 先确认
f.contains("geometry"),再f.at("geometry").contains("type")和f.at("geometry").contains("coordinates") - 坐标数组类型不确定:
Point是[x,y](json::array_t长度为 2),LineString是[[x,y], [x,y]](二维数组),Polygon是三维(外环+内环)。用f.at("geometry").at("coordinates").size()判断维度,别硬转std::vector<:vector>></:vector> -
properties是自由结构,用f.at("properties").is_object()检查后,再用.value("name", "")安全取默认值,避免.at("name")崩溃
坐标系和精度问题在解析层无法解决,但必须留出接口
nlohmann/json 只管把数字当 double 解出来,它不管这是 WGS84 经纬度还是 Web Mercator 米制坐标。GeoJSON 规范明确要求坐标为 [longitude, latitude](即 EPSG:4326),但实际数据经常不守规矩——比如国内某些导出工具会输出 GCJ-02 偏移坐标,或把 coordinates 顺序写成 [lat, lon]。
解析代码里不做坐标转换,但必须让调用方能轻易干预。常见做法是在解析 loop 里暴露原始 coordinates 数组引用,而不是立刻转成自定义 Point 结构体。
- 不要写
auto pt = Point{coord[0].get<double>(), coord[1].get<double>()}</double></double>这种紧耦合代码 - 推荐返回
std::vector<:vector>></:vector>或json类型的coordinates字段,由上层决定是否调用 PROJ 或 GDAL 转换 - 如果必须存为内部结构,用
struct Coord { double x; double y; };而非lat/lon命名,避免语义误导
性能敏感时避免重复解析和深拷贝
一个含上千 features 的 GeoJSON 文件,用 json::parse() 生成的 DOM 树内存占用可能达数 MB,且每次访问 .at("features")[i].at("geometry") 都是 O(1) 但带 hash 查找开销。高频场景(如实时渲染)下,反复解析同一份数据是明显瓶颈。
真正该优化的不是解析逻辑本身,而是复用策略和视口裁剪——解析是一次性的,后续操作应基于内存中已有的 json 对象,而非反复从字符串重 parse。
- 把解析结果缓存在类成员变量里,用
const json&引用传递,禁止json j = parsed_json这种隐式拷贝 - 如果只关心视口内的 features,解析完立即用 bounding box(
geometry的coordinates极值)做过滤,别等全部解析完再遍历 - 不用
json::dump()回写调试——日志直接打印j.at("features").size()和前几个f.at("properties").dump()就够了,dump 整体太慢
contains(),也不要靠文档赌数据质量。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










