GeoJSONcn
GeoJSONcn / 技术专栏 / GeoJSON 里的 prope…

GeoJSON 里的 properties 老坑人?行政区划属性字段的类型、命名与空值清坑指南

发布于 2026-08-16 · GeoJSONcn 技术团队 · 阅读约 11 分钟

下载的行政区划 GeoJSON 里,properties 似乎是最不起眼的那段——坐标对不对才是大家关心的,属性嘛,用的时候读一眼就行。可跑过几次真实项目就发现,翻车往往不是几何,而是属性。今天把 GeoJSON 属性字段那些坑和清理办法摊开讲一遍。无论你是做 GeoJSON下载 后直接上 Leaflet,还是要喂给后端空间库,这几点都值得先花十分钟排查。

字段类型:数字被存成字符串,是大部分 bug 的源头

我从各类源站拿到过全国省市区县geojson数据下载回来的文件,第一件要确认的事就是每个字段到底是数字还是字符串。JSON 是弱类型,很多工具从 CSV、Excel、Shapefile 导出来时会偷懒:

行政区划代码尤其危险。.geojson(RFC 7946)里代码必须保留前导零,比如 510722(绵阳三台县)。如果被当成数字写入,前导零直接丢,变成 510722 看着一样,但遇到 11 开头的北京区县,"110000" 会变成 "11",join 全错。我写过一个极小的归一化函数:

// 行政区划代码统一转字符串并补齐 6 位,防御前导零丢失
function normCode(v) {
  if (v == null) return null;
  const s = String(v).trim();
  // 兼容统计用 12 位与常规 6 位,统一取前 6 位
  return s.length >= 6 ? s.slice(0, 6) : s.padStart(6, '0');
}

再配合一个表来对照常见字段的类型陷阱,判断你的数据该不该修:

字段正确类型常见错误后果
adcode / codestringnumber前导零丢失,join 错
name / 名称string—重名、混用简繁体
population / 面积numberstring数值运算变拼接
中心点坐标arraystring解析失败
可选描述字段null 或缺省空串 " "渲染空标签

修的话不要手动一行行改,写个脚本遍历 features 批量归一化,改完再 JSON.stringify(result, null, 2) 重新落盘,顺手做一次几何合法性校验(几何不合法是另一篇的事,这里不展开)。下面这段把整份文件读进来、字段规整一遍再写回:

const fs = require('fs');
const gj = JSON.parse(fs.readFileSync('sichuan.geojson', 'utf8'));
for (const f of gj.features) {
  const p = f.properties;
  if (p.adcode) p.adcode = normCode(p.adcode);
  if (typeof p.population === 'string') p.population = Number(p.population);
}
fs.writeFileSync('sichuan.clean.geojson', JSON.stringify(gj));

注意 normCode 里那行 s.slice(0, 6):如果上游混进了统计用 12 位代码,直接截前 6 位能救回一部分;但要是 6 位本身被截断过,那就只能回源头修了。所以脚本加个计数,打印有多少要素的 adcode 长度既不是 6 也不是 12,人工看一眼再决定。

字段命名:中文本地化与冗余属性

很多源数据为了让数据库看得懂,字段名用拼音:XZQDM、XZQMC、JCCLASS。直接拿去给前端渲染没问题,但你自己维护、给同事交接、或挂到别的地图场景时,拼音字段名可读性极差。我在做村级数据的时候就吃过亏:一套全村的数据里既有 village 又有 czmc,字段语义重复,后面接手的同事根本分不清哪个是村级名。

字段没统一还有一个隐患——跨文件 join 时对不上号。比如你要把一份统计报表按 乡镇代码 接回地理文件,但报表里叫 town_code,边界里叫 czdm,不写映射表就只能靠肉眼。建议在下发前统一定一套,并保留一份中英对照清单。

建议在下发前统一成一套命名,保留必选、砍掉冗余,properties 尽量精简。行政区划边界数据常见的精简原则是:

属性越瘦,前端序列化、边缘缓存、按需加载全都跟着受益。毕竟全国省市区县区划边界数据下载下来是要给别人的应用消费的,字段干净才能少出兼容问题。字段名最好用英文 snake_case(如 full_name 而非 fullname),再在数据说明文档里贴一张中英对照,别让下游靠猜。

空值与缺失:别用空字符串占位

最让我头疼的是 null 的写法不统一:有的要素 "name": ""、有的干脆没有 name 这个 key、有的写 "population": null。三种写法在 JS 里的表现不一样,undefined、null、"" 在模板字符串拼标签时会渲染成不同的东西,String(feature.properties.name) 更是直接给你吐一个 "null"。

统一策略很简单:该有的字段必须有,缺失就不写那个 key;可选度量值缺则用 null,别用空串。渲染端再用可选链兜底:

const name = p?.name ?? '未命名';
const pop  = p?.population ?? 0;

这样前端永远拿得到可用的默认值,不会因为某个要素属性不全而整片白屏。

小结

GeoJSON 的属性字段看着小,实则决定了 join 对不对、运算准不准、渲染稳不稳。做全国省市区县geojson数据下载分发时,把字段类型、命名、空值这三件小事在源头做干净,比事后在十几个消费方里各打一份补丁省事得多。至于全国村级geojson数据下载这类更细粒度的数据,字段规范更值得提前定好——村级要素动辄成千上万,改一处就等于重发一遍。

需要能直接用的分层数据,可以在 geojsoncn.com 上预览(免费),确认字段结构后再下载(导出 ¥1.99/次)。