地址校验与规范化常被当成同一件事写进需求里,结果是两边都没做好:该拦住的不拦,不该拦的乱拦。这篇把两件事分开讲——规范化管写法,校验管存在性——并说明为什么后者的能力在全世界范围内都有上限,读完你能给自己的地址处理流程排出正确的先后顺序,也能判断某个「地址校验服务」到底在卖什么。
规范化到底做了什么
规范化的目标是把同一地址的不同写法收敛成一种。它做的事通常是:统一大小写与全半角、去掉多余空格、把行政区名换成标准写法、把邮编补全或者按国家格式切开、必要时把缩写展开成完整词。
它不判断地址是否真实存在。一个不存在的门牌号,只要写法规范,照样能通过规范化。所以规范化适合放在用户输入之后、写入数据库之前,作为清理步骤;把它当成校验来用,会让一批语法正确但根本不存在的地址顺利入库。
真校验能做到什么程度
真正意义上的校验要回答的是另一组问题:这个地址是否存在、能不能投递、投递员今天能不能找到。能做到的程度取决于有没有官方数据支撑。有官方地址库的国家,可以做到具体到门牌的存在性检查;没有的,就只能检查格式是否合理、行政区与邮编是否落在彼此对应的范围内。
也就是说,多数系统里的校验实际上只能做到看起来合理。把这一点写进需求文档很重要,否则团队会期待一个程序化校验能消灭所有错误地址,最后在验收时才发现做不到。
把能力分层看会更清楚。最下面一层是字符与长度,纯本地计算就能完成,成本最低、误判也最少。中间一层是字段之间的对应关系,例如行政区是否存在、邮编是否落在这个行政区的范围内,需要一份随行政区划更新的对照数据。最上面一层才是门牌级的存在性判断,成本高、覆盖的国家有限,通常按次计费。多数项目真正需要的是前两层,第三层只值得用在错误成本特别高的场景,比如跨境物流的首公里揽收。
为什么没有全球权威的地址总库?
因为地址不是一个统一的命名系统,而是各国邮政与地方政府各自维护的投递体系。它们的数据结构不同、更新节奏不同、对外开放程度也不同,没有人负责把它们合并成一份实时快照。即便在同一个国家内部,也可能存在几套不完全一致的来源。
现实中的地址校验服务多以拼装为主:组合若干国家或地区的官方或商业数据,再对没有数据的地区退回到格式校验。这不代表服务不好用,而是说明它的覆盖范围和准确度是有边界的,你在选型时应当问清楚覆盖到哪些国家、更新频率如何。
一个正则表达式能验完所有地址吗?
不能。正则语言长于描述字符的形状,短于表达跨字段的约束,更无法知道某个门牌是否存在。用它写出来的「万能地址正则」通常只有两种结局:松到把明显错误的输入放过去,或者紧到把合法地址拦下来,而后者对业务的伤害更大。
正则的合理位置是校验单个字段的形状——邮编的位数与字符集、州缩写是否在列表里、门牌号是否为纯数字。跨字段的关系则应当交给结构化规则:邮编与行政区的对应、城市与行政区的归属。邮编这一类字段的具体处理见各国邮编格式。
校验失败时该允许人工覆盖吗?
应该允许,而且要有记录。原因很直接:校验本身有上限,误判一定存在。如果系统在校验失败时只给一个死路,真实用户就会被卡住,而他们的地址可能完全没问题。
合理的做法是给出改动建议——比如提示城市与邮编不匹配,让用户确认后仍然可以提交,同时把这次覆盖记录在案。这样既能改进数据质量,也不会把系统的局限转嫁给用户。对内部系统而言,覆盖记录还能反过来告诉你校验规则在哪些国家过于严格。
还有一条容易被跳过的处理:规范化改动过的字段应当留下痕迹。把用户输入的原文与规范化后的结果放在同一处,既能解释为什么界面上显示的和用户输入的不一样,也能在规范化规则出错时回滚。丢失了原文,这类问题就只能靠猜。
给开发者:先规范化,再校验
顺序不是风格问题。先规范化能让校验面对的输入更统一,减少同一地址因为空格或大小写差异被区别对待;反过来做则会让校验规则被迫兼容各种脏输入,规则会越写越复杂。
顺序之外还有一个取舍:规范化要不要替用户改写地址。改写能提高一致性,但也可能把用户真实想写的内容改错,尤其是本地方言写法与复合路名。一个折中的做法是只做不会改变含义的清理——去空格、统一全半角、统一大小写——而把替换行政区名这类可能改变语义的操作放到提示层,由用户确认。
以下几件事值得在实现前定下来:
- 规范化只做可逆的变形,不要在这一步丢失用户输入的原文。
- 校验分为格式校验与存在性校验两级,前端只做格式校验,需要联网查询的存在性校验放在服务端。
- 跨字段规则单独维护成表,按国家组织,不要写进通用的万能校验函数。
- 校验失败要区分可修正与不可修正,给出具体到字段的提示。
- 覆盖提交要留痕,并且把覆盖率当作观测指标。
测试数据同样要覆盖这两类:格式正确但不存在的地址、格式不规范但真实存在的地址,以及行政区与邮编不匹配的地址。构造方式见测试固定装置里的地址数据,多国格式样本可以直接用随机地址生成器生成,它保证城市、行政区与邮编取自同一条记录,正好用来验证你的规范化步骤会不会把一致的字段改坏。用来做校验与边界测试的地址一律只用于测试,不能投递。
下一步
检查一遍你的流程顺序:用户输入之后是不是先做规范化、再做分级校验、最后才落库;校验失败是不是有出口。这两步改完,地址数据的质量提升通常比再加十条正则明显。如果你正在准备跨国家的地址样本,先读国际地址格式,把字段语义定对,再去写校验规则会顺很多。