郵便番号のフォーマットは互換性がなく、5桁を前提としたバリデータは世界の大半を拒否してしまいます。違いは見た目ではなく構造にあります。先頭ゼロを含む数値式のシステム、文字と数字が混在するシステム、都市名の前にコードを置くシステムがあり、このサイトのフィクスチャセットに含まれる38か国のうち2か国には郵便番号がまったく存在しません。
このリファレンスは、住所フォームを構築する開発者にとって重要なパターンを、直接テストできる正規表現とともにまとめたものです。また、このサイト自体が引いている線引きも示します。ここでの郵便番号検証は全38か国に対する構造チェックに加え、US ZIPについては40,979行のデータセットに対する存在チェックです。このガイドのいかなる記述も、一致したコードが割り当て済みであることや配達可能であることを意味するものではありません。
郵便番号が数値フィールドでない理由
米国は5桁またはZIP+4を使用するため、開発者は郵便番号を整数としてモデル化したくなります。しかしこのモデルは、文字がコードの一部であるカナダ、イギリス、オランダ、アイルランド、マルタ、アルゼンチンでは即座に破綻します。また、先頭ゼロが意味を持つドイツ、フランス、スペイン、イタリア、ポーランドでも、整数カラムがゼロを落としてしまうため、静かに破綻します。
2つ目のバグの種類は位置に起因します。ほとんどの西欧諸国は都市名の後に郵便番号を置きますが、ドイツ、フランス、オランダ、日本は都市名の前に置き、日本はコード全体を住所の先頭に置きます。フォームが固定テンプレートをレンダリングする場合、すべてのフィールドが埋まっていても、現地の読み手には明らかに間違っている住所が生成されてしまいます。
- 郵便番号は常にテキストとして保存し、整数にはしない
- CSVエクスポートを含むすべてのレイヤーで先頭ゼロを保持する
- 国が厳密に数値式でない限り文字を許可する
- 郵便番号が都市名の後に来ると仮定しない
- 区切り文字は構造ではなく表示上のものとして扱う
数値式システムとその範囲
ヨーロッパの大半は固定長の数値コードを使用します。ドイツ、フランス、スペイン、イタリア、ギリシャ、トルコ、サウジアラビアは5桁、オーストリア、ベルギー、スイス、デンマーク、ノルウェー、ハンガリー、南アフリカは4桁、ポーランドとポルトガルはハイフンを追加し、スウェーデンは3桁、スペース、2桁です。チェコは5桁で、通常は3桁目の後にスペースを入れて書きます。
アジアとラテンアメリカは主に数値式ですが長さが異なります。インド、中国、ロシア、シンガポール、ナイジェリアは6桁、日本は7桁で慣例的に3桁目の後にハイフンを入れ、韓国は5桁、ブラジルは8桁で5桁目の後にハイフンを入れ、チリは7桁、コロンビアは6桁、ペルーとメキシコは5桁です。長さだけでは国を特定できないため、バリデータは何かを検証する前に国フィールドを必要とします。
| 国 | 桁数 | 標準形式 | 正規表現 |
|---|---|---|---|
| ドイツ | 5桁 | 10115 | ^\d{5}$ |
| フランス | 5桁 | 75008 | ^\d{5}$ |
| スペイン | 5桁 | 28013 | ^\d{5}$ |
| オーストリア | 4桁 | 1010 | ^\d{4}$ |
| ポーランド | 5桁+ハイフン | 00-001 | ^\d{2}-\d{3}$ |
| ポルトガル | 7桁+ハイフン | 1250-096 | ^\d{4}-\d{3}$ |
| スウェーデン | 5桁+スペース | 114 55 | ^\d{3}\s\d{2}$ |
| 日本 | 7桁+ハイフン | 100-0001 | ^\d{3}-\d{4}$ |
| ブラジル | 8桁+ハイフン | 01310-100 | ^\d{5}-\d{3}$ |
| インド | 6桁 | 110001 | ^\d{6}$ |
| 韓国 | 5桁 | 04524 | ^\d{5}$ |
| メキシコ | 5桁 | 06600 | ^\d{5}$ |
英数字式システムとその文字規則
カナダはA1A 1A1パターンを使用し、文字が制限されています。最初の文字はD、F、I、O、Q、U、W、Zにできず、残りの文字はD、F、I、O、Q、Uにできません。2つの3文字グループ間のスペースは慣例です。任意の文字を許可するバリデータは、Canada Postが決して発行しないコードを受け入れてしまいます。
イギリスは2〜4文字のアウトワードコード、1つのスペース、3文字のインワードコードを使用し、SW1A 1AAのようになります。オランダは4桁、スペース、2つの大文字です。アイルランドは7文字のEircodeで、3文字のルーティングキーと4文字の一意識別子に分かれます。マルタは3文字、スペース、4桁です。アルゼンチンは8文字のCPAで、文字の後に4桁、3文字が続き、例えばC1425ABCです。
| 国 | パターン | 例 | 正規表現 |
|---|---|---|---|
| カナダ | A1A 1A1(文字制限あり) | K1A 0B1 | ^[ABCEGHJKLMNPRSTVXY]\d[ABCEGHJKLMNPRSTVWXYZ] ?\d[ABCEGHJKLMNPRSTVWXYZ]\d$ |
| イギリス | 2〜4文字のアウトワード、3文字のインワード | SW1A 1AA | ^[A-Z]{1,2}\d[A-Z\d]? ?\d[A-Z]{2}$ |
| オランダ | 4桁、2文字 | 1012 AB | ^\d{4} ?[A-Z]{2}$ |
| アイルランド | 3文字のルーティングキー、4文字の識別子 | D02 X285 | ^(?:[A-Z]\d{2}|D6W) ?[A-Z0-9]{4}$ |
| マルタ | 3文字、4桁 | VLT 1117 | ^[A-Z]{3} ?\d{4}$ |
| アルゼンチン | 文字、4桁、3文字 | C1425ABC | ^[A-Z]\d{4}[A-Z]{3}$ |
郵便番号のない国
香港とアラブ首長国連邦には郵便番号システムがありません。どちらもこのサイトの38か国フィクスチャセットに含まれており、ジェネレーターは数字をでっち上げるのではなく、空の郵便番号値を返します。これは正しい動作であり、有用なテストケースでもあります。郵便番号を必須とするフォームは、両市場で壊れているからです。
UAEの慣例はP.O. Box番号であり、これは郵便番号ではないため、そのフィールドに押し込めるべきではありません。香港の住所は地区と通りを使用し、郵便物はコードなしで配達されます。データモデルが非nullの郵便番号値を要求する場合は、偽のコードではなく、国レベルのフラグのような明示的なセンチネルを使用してください。偽のコードは検証を通過してしまい、その後、実在のコードを前提とするすべての下流チェックで失敗するからです。
- 香港:郵便番号なし、地区と通りが住所
- アラブ首長国連邦:郵便番号なし、P.O. Boxが一般的な慣例
- いずれかの国が選択された場合は郵便番号フィールドを任意にする
- 郵便番号カラムに00000やN/Aを決して代入しない
- エクスポートが欠損データに見えないよう、不在を明示的に記録する
構造チェックと存在チェック
構造チェックは、文字列が国のパターンに一致するかを答えます。存在チェックは、コードが参照データセットに現れるかを答えます。コードが一度も割り当てられていないことを教えられるのは2つ目だけです。このサイトは全38か国に対して構造チェックを、US ZIPに対して40,979行のデータセットに対する存在チェックを実行し、一方を他方と混同しないよう異なるラベルを付けています。
どちらのチェックも配達可能性を証明しません。5桁のUS ZIPが存在しても、その下の番地が存在しないことはあり得ますし、構造的に有効なドイツのコードが、指定された都市とは別の都市に属することもあります。そのレベルの保証が必要なら、郵便参照データセットと番地レベルのデータベースが必要であり、それはフォーマットチェッカーとは別の製品です。
| チェック種別 | 対象 | 証明すること | 証明しないこと |
|---|---|---|---|
| パターン一致 | 全38か国 | その国にとって整形済みであること | コードが割り当て済みであること |
| US ZIP存在チェック | 40,979行のUS ZIP | コードがデータセットに存在すること | 都市や番地の一致 |
| 必須フィールド規則 | フォームレベル | 送信を進められること | 実世界での有効性 |
| 長さと文字セット | フィールドレベル | ストレージがオーバーフローしないこと | 国の正しさ |
本番バグを引き起こす正規表現の詳細
すべてのパターンをアンカーしてください。アンカーなしの/\d{5}/は9桁の文字列内の5桁に一致し、成功を報告します。^と$、または同等の完全一致APIを使用してください。JavaScriptでは\dはASCII数字のみに一致しますが、Pythonでは\dがデフォルトでUnicode数字に一致するため、re.ASCIIでコンパイルするか[0-9]と書かない限り、パターンが東アラビア数字を受け入れてしまいます。
区切り文字が必須かどうかを明示的に決めてください。表示時は標準の区切り文字を自分で挿入します。入力時は0個または1個のスペースやハイフンを受け入れ、正規化します。文字クラス内のハイフンには注意してください。エスケープするか最後に置かない限り範囲を定義してしまいます。また、正規化のバグを大文字小文字を区別しないフラグで覆い隠さないでください。書き込み時に値を大文字にし、表示形式は標準のままにします。
- ^と$でアンカーするか、完全一致関数を使用する
- ASCII数字を意味する場合は[0-9]を使用する
- 入力時は任意の区切り文字を受け入れ、表示時は標準の区切り文字を出力する
- ハイフンはエスケープするか文字クラス内の最後に置く
- 大文字小文字フラグを散らすのではなく、マッチ前に大文字化する
- 非改行スペースやゼロ幅文字は明示的に拒否する
書き込み時に正規化し、表示時に整形する
1つの標準形式を保存し、表示形式を導出します。標準形式は通常、標準の区切り文字付きの大文字、または区切り文字が純粋に慣例的な場合は数字のみです。正規化は不可逆であるため、監査証跡が必要な場合は生のユーザー入力を別のカラムに保持してください。サポート担当者が入力された内容を正確に確認する必要があるかもしれません。
国別の正規化は小さいながらも実在します。カナダは大文字の文字-数字-文字、スペース、数字-文字-数字です。オランダは数字の後の文字を大文字にします。イギリスは1つのスペースと大文字です。ブラジルと日本はユーザーがしばしば省略するハイフンを使用するため、ハイフン付き形式に正規化します。ドイツは区切り文字をまったく使わず、先頭ゼロを保持する必要があります。
| 国 | 生の入力 | 保存する標準形式 | 表示 |
|---|---|---|---|
| カナダ | k1a0b1 | K1A 0B1 | K1A 0B1 |
| オランダ | 1012ab | 1012 AB | 1012 AB |
| イギリス | sw1a1aa | SW1A 1AA | SW1A 1AA |
| ブラジル | 01310100 | 01310-100 | 01310-100 |
| 日本 | 1000001 | 100-0001 | 100-0001 |
| ドイツ | 10115 | 10115 | 10115 |
| スウェーデン | 11455 | 114 55 | 114 55 |
コピーして使えるテストコーパス
すべてのバリデータには、国ごとに少なくとも1つの有効ケースと1つの無効ケース、さらに正規化とストレージを特にテストするケースを含むコーパスが必要です。以下の表は出発点となるセットです。無効ケースのいくつかは一般的な理由ではなく国固有の理由で無効であることに注目してください。手書きのテストが早すぎる段階で止まるのはまさにこの点です。
郵便番号のない国、先頭ゼロ、ユーザーが実際に入力する区切り文字のバリアントのケースを追加してください。バリデータがクライアントとサーバーで共有されている場合は、同じコーパスを両方の実装に対して実行してください。寛容なクライアントと厳格なサーバーの間の不一致は、「フォームは受け入れたのにAPIが拒否した」という報告の最も一般的な原因です。
| ケース | 値 | 国 | 期待結果 |
|---|---|---|---|
| 有効なZIP+4 | 97205-2515 | アメリカ合衆国 | 受け入れ |
| 無効なZIP+4 | 97205-251 | アメリカ合衆国 | 拒否 |
| 有効なカナダ | K1A 0B1 | カナダ | 受け入れ |
| 不正なカナダの文字 | D1A 0B1 | カナダ | 拒否 |
| 有効なイギリス | SW1A 1AA | イギリス | 受け入れ |
| イギリスのインワード欠落 | SW1A | イギリス | 拒否 |
| ドイツの先頭ゼロ | 01067 | ドイツ | 受け入れ、かつ保持 |
| 数値式システム内の文字 | 1011A | ドイツ | 拒否 |
| コードなし | 香港 | 空として受け入れ | |
| でっち上げコード | 99999 | アラブ首長国連邦 | フィールドを拒否 |
よくある質問
- 香港とアラブ首長国連邦にはなく、どちらもこのサイトの38か国フィクスチャセットに含まれています。ジェネレーターは値をでっち上げるのではなく、空の郵便番号フィールドを返します。
- いいえ。構造一致は値が整形済みであることだけを意味します。ここではUS ZIPのみが40,979行に対する存在チェックを受け、どの国も配達可能性の主張は受けません。
- 決してそうすべきではありません。カナダ、イギリス、オランダ、アイルランド、マルタ、アルゼンチンは文字を使用し、ドイツ、フランス、スペイン、イタリア、ポーランドは意味のある先頭ゼロを持ちます。
- オランダのコードは4桁の後に2つの大文字が続き、例えば1012 ABです。文字は地域の接尾辞ではなくコードの一部であり、数字のみの正規表現は有効な住所を拒否します。
- 0個または1個のスペース付きの入力を受け入れ、大文字化し、単一の標準区切り文字を保存してください。ユーザーが入力した内容をそのまま返すのではなく、表示には標準形式を出力してください。
郵便番号のない国はどこですか?+
有効な郵便番号は住所が実在することを意味しますか?+
郵便番号は整数として保存すべきですか?+
なぜオランダは数字の後に文字を置くのですか?+
イギリスやカナダのコードのスペースはどう扱うべきですか?+
例は合成データです。生成された住所を本人確認、アカウント登録、配送に使用しないでください。