世界各国地址格式:开发者实用指南
每一个地址表单都内置了假设,而这些假设通常来自写表单的人自己所在的国家。一个在加州开发的结账页面,会默认门牌号在前、有城市、有两字母州缩写、邮编是五位数字。第一位来自伦敦、东京或柏林的用户,会替你验证这些假设哪里错了——往往是卡在一个在他们国家根本不存在的必填字段上。
本文梳理各国真实地址格式的差异、这些差异如何让软件出错,以及如何在用户踩坑之前,用多国生成测试数据来检验你的表单、解析器和数据库。全文完全从开发与 QA 视角出发:这是一份"不测就会出问题"的清单。
为什么没有全球统一的地址格式
邮寄地址从来不是被"设计"出来的,而是历史堆积的产物。每个国家的格式都源自各自的土地登记、城市规划和邮政体系,各国邮政再把邮递员早已习惯的写法标准化。万国邮政联盟只协调国家之间的投递,刻意不强制统一版式——地址按目的地国的规则书写,而非寄件国的规则。
对软件来说,这意味着不存在一个能无损容纳所有地址的统一 Schema。"州"字段在美国是必填项,在英国毫无意义,在日本则会引起困惑——对应的行政单位是都道府县,而且写在地址的另一端。任何一个僵硬的单一 Schema,本质上都是在赌你的用户全部住在同一个国家。用多国地址做测试,就是找出这个赌注在哪里输掉。
门牌号在前,还是街道名在前?
英语国家通常门牌号在前:美国的 12 Main St、英国的 221B Baker Street、澳大利亚的 4 Wattle Lane。欧洲大陆多数国家正好相反:德国地址写作 Musterstraße 12,西班牙写 Calle Mayor 12,荷兰写 Hoofdstraat 12——街道名在前、号码在后,还常带 12a、12-14 这类后缀。
这对解析和展示代码影响最大。如果你用一个期望开头是数字的正则去拆分投递行,Musterstraße 12 要么校验失败,要么字段被拆反。如果你用结构化字段重新拼装地址,把顺序硬编码成"号码 + 街道",德国地址就会被打印成反的。两种方向都要测:把"号码在前"和"街道在前"的样本,喂给所有拆分、校验、拼接街道行的代码路径。
从大到小 vs 从小到大
西方地址从小写到大:收件人、街道、城市、地区、国家。日本和中国正相反。日本地址以邮编和都道府县开头,逐级缩小到市区町村、丁目、番地和建筑——常常根本没有街道名,因为日本多数街道无名,建筑按街区编号。中文地址的原生写法依次是省、市、区、路、号、楼、室,收件人姓名在最后。
软件里的陷阱在于默认"第一行总是最具体的一行"。以首行为键做排序、去重或"是否同一地址"比对的逻辑,会把两个不同的东京公寓判定为相同,因为它们都以都道府县开头。标签打印是另一个经典翻车现场:按西方顺序自上而下输出字段的模板,会打出一张日本邮递员必须从下往上读的面单。
"城市"到底指什么?
连最普通的"城市"字段,在不同国家含义也不同。在美国它是与州配对的建制市。在英国惯例上填的是 post town(邮政镇)——一个邮政路由概念,可能和居民自认为的居住地并不一致,而郡在现代英国地址中是可选的。在澳大利亚这个字段填的是 suburb(城区),比美国的城市小得多,与州/领地缩写和四位邮编搭配使用。
实际结论是:"城市"应当作为自由文本的地点字段处理,而不是拿你恰好知道的城市列表去校验。地点下拉框只有在按国家使用权威数据时才可行,否则就会变成合法用户翻不过去的墙。来自美国、英国、澳大利亚的生成地址,会在这个字段里分别填入形态完全不同的值——这正是你的校验逻辑需要经受的多样性。
各国邮编形态各异
邮编是开发者最爱过度校验的字段。美国用五位 ZIP,如 90210,可扩展为 ZIP+4。德国和法国同样是五位数字,但地理逻辑不同,且存在会被整数列吃掉的前导零。日本是带连字符的七位:NNN-NNNN,如 100-0001。中国是六位数字,澳大利亚是四位。然后是字母数字混合型:英国邮编如 SW1A 1AA,前半段长度可变;加拿大邮编按"字母-数字-字母 数字-字母-数字"交替排列:A1A 1A1,中间惯例上有空格。
有三个 Bug 值得专门去抓。第一,"纯数字"假设:type=number 的输入框或 \d+ 正则会拒绝所有英国、加拿大用户。第二,固定长度假设:合法邮编从四个字符到八个以上不等,还可能带空格和连字符。第三,静默归一化:把 SW1A 1AA 的空格或 100-0001 的连字符去掉,内部存储也许没问题,印在快递面单上就是错的。用一批覆盖这七个国家的生成地址跑一轮测试,三个 Bug 会同时现形。
设计并测试经得起考验的地址表单
最稳妥的设计是更少、更宽松的字段:一到两行自由地址行、一个地点行、可选的地区字段、自由文本邮编,以及一个驱动字段标签变化的国家选择器。如果确实需要结构化字段,就按国家适配:把 State 改标为 Province 或 Prefecture,在不存在的国家直接去掉,永远不要用一个国家的邮编正则去校验另一个国家的用户。字段要留足余量:每行至少允许 100 个字符,并全链路使用 Unicode 存储——Musterstraße、東京都、北京市必须完好无损地穿过你的数据库、API 和 PDF。
然后像验证其他需求一样去验证它:用测试数据。从几个刻意差异化的国家——美国、英国、德国、日本、中国、加拿大、澳大利亚——生成地址,推过所有接触地址的环节:注册与结账表单、服务端校验、数据库存储、搜索、去重、面单与发票渲染。盯住这些症状:变音符被截断、字母数字邮编被拒、前导零丢失、必填字段无解。每一个失败都是真实国际用户迟早会撞上的真实 Bug;生成数据只是让你在预发布环境、而不是生产环境遇见它。
常见问题
地址应该用一个自由文本框,还是拆成结构化字段? +
如果只是展示或打印地址,自由文本行更安全,也更贴近人们的真实写法。只有当下游确实需要结构化数据——税务规则、运费查询、区域统计——才拆字段,并且按国家适配,而不是把一个国家的版式强加给所有人。
面向国际用户,邮编应该怎么校验? +
按国家校验,且在用户选定国家之后再校验。如果无法维护逐国规则,就接受任意较短的、可含空格和连字符的字母数字串。把美式五位数字正则全球通用,等于拒绝所有合法的英国、加拿大和日本邮编。
为什么邮编要存成字符串而不是数字? +
因为很多邮编根本不是数字。英国和加拿大的邮编含字母,日本的含连字符,德国、法国和美国部分邮编以 0 开头——整数列会悄悄删掉这个前导零。一条生成的德国地址(如 01067 Dresden)一次插入就能让这个 Bug 现形。
生成的地址能替代真实地址数据做测试吗? +
在格式、UI 和数据管道测试上可以——生成地址复现了各国地址的结构,又不暴露任何真实个人信息。但可投递性和地理编码精度测试仍需权威邮政数据,因为随机组合不保证对应真实的投递点。