Java Tips | 文字列処理:郵便番号チェック

Java Java
スポンサーリンク

郵便番号チェックは「“7桁の数字っぽいもの”だけを通す」ための技

住所入力フォーム、配送先登録、請求書の宛先設定…。
業務システムで「郵便番号」を扱う場面もかなり多いですよね。

ここで何もチェックしないと、
「123」「abcdefg」「000-0000」みたいな、明らかにおかしい値がDBに入ってしまいます。
後で住所検索が失敗したり、帳票が変な表示になったり、データが汚れたりします。

そこで使うのが 郵便番号チェック
これは「この文字列が“郵便番号としてあり得る形かどうか”をざっくり判定する」ためのユーティリティです。
完璧な判定ではなく、「明らかにおかしいものを早めにはじくフィルタ」として捉えるのがちょうどいいです。


まずは「日本の郵便番号のざっくりルール」を決める

完璧を目指さず“現場で困らないライン”を決める

日本の郵便番号は、基本的に「7桁の数字」です。
ユーザー入力では、だいたい次の2パターンが多いです。

1234567(ハイフンなし)
123-4567(3桁-4桁)

これをベースに、まずはこんなルールを決めてしまうのが現実的です。

数字とハイフン以外は許可しない
ハイフンなしなら 7 桁の数字
ハイフンありなら 3桁-4桁 の形

ここまでチェックすれば、「明らかに郵便番号じゃないもの」はかなり弾けます。
「その番号が本当に存在するか」は別問題なので、まずは“形式”だけを見る、という割り切りが大事です。


シンプルな郵便番号形式チェックユーティリティ

正規表現で「7桁 or 3桁-4桁」を判定する

まずは、よくある2パターンだけを許可するチェックを書いてみます。

import java.util.regex.Pattern;

public final class PostalCodeValidator {

    private PostalCodeValidator() {}

    // 7桁の数字、または 3桁-4桁
    private static final Pattern SIMPLE_JP_POSTAL =
            Pattern.compile("^(\\d{7}|\\d{3}-\\d{4})$");

    public static boolean isValidFormat(String postalCode) {
        if (postalCode == null) {
            return false;
        }
        return SIMPLE_JP_POSTAL.matcher(postalCode).matches();
    }
}
Java

使い方はこうなります。

System.out.println(PostalCodeValidator.isValidFormat("1234567"));   // true
System.out.println(PostalCodeValidator.isValidFormat("123-4567"));  // true

System.out.println(PostalCodeValidator.isValidFormat("1234-567"));  // false
System.out.println(PostalCodeValidator.isValidFormat("12-34567"));  // false
System.out.println(PostalCodeValidator.isValidFormat("123456"));    // false
System.out.println(PostalCodeValidator.isValidFormat("12345678"));  // false
System.out.println(PostalCodeValidator.isValidFormat("abc-4567"));  // false
System.out.println(PostalCodeValidator.isValidFormat("123-45a7"));  // false
Java

ここで深掘りしたい重要ポイントは三つです。

一つ目は、「正規表現で“許可する形を限定している”」ことです。
\\d{7} は「数字7桁」、\\d{3}-\\d{4} は「数字3桁-数字4桁」を表します。
(A|B) は「A または B」という意味なので、
「7桁」か「3桁-4桁」のどちらかだけを許可している、ということになります。

二つ目は、「^$ で“文字列全体がその形であること”を保証している」ことです。
これがないと、abc1234567xyz のような文字列にもマッチしてしまいます。
形式チェックでは、「全体がその形かどうか」を見るのが基本です。

三つ目は、「null をそのまま false にしている」ことです。
「未入力かどうか」と「形式が正しいかどうか」は、本来別の話なので、
呼び出し側で null や空文字チェックをしたうえで、このメソッドを呼ぶのがきれいな設計です。


ハイフンを抜いた「純粋な7桁」を取り出すユーティリティ

後続処理のために「正規化」しておく

郵便番号を使って住所検索をしたり、外部APIに投げたりするときは、
「ハイフンなしの7桁」で扱うことが多いです。

そこで、「形式チェック」とセットで「正規化(normalize)」のユーティリティを用意しておくと便利です。

public final class PostalCodeUtil {

    private PostalCodeUtil() {}

    public static String normalizeTo7Digits(String postalCode) {
        if (postalCode == null) {
            return null;
        }
        // 空白をトリム
        String trimmed = postalCode.trim();
        // 形式が正しくなければ null を返す
        if (!PostalCodeValidator.isValidFormat(trimmed)) {
            return null;
        }
        // ハイフンを除去して7桁にする
        return trimmed.replace("-", "");
    }
}
Java

使い方はこうです。

System.out.println(PostalCodeUtil.normalizeTo7Digits("1234567"));   // 1234567
System.out.println(PostalCodeUtil.normalizeTo7Digits("123-4567"));  // 1234567
System.out.println(PostalCodeUtil.normalizeTo7Digits(" 123-4567 "));// 1234567
System.out.println(PostalCodeUtil.normalizeTo7Digits("1234-567"));  // null(形式不正)
Java

ここでのポイントは、「“チェック”と“正規化”を分けて考える」ことです。

入力フォームでは、

形式が正しいかどうかをチェックしてエラーメッセージを出す
内部処理では、正規化された7桁を使う

という役割分担にしておくと、コードがとても読みやすくなります。


例題:入力フォームでの郵便番号チェック

ユーザー登録フォームで、郵便番号を入力してもらう場面を考えます。

サーバ側では、こんな感じで使えます。

String postal = request.getParameter("postalCode");

if (postal == null || postal.isBlank()) {
    errors.add("郵便番号を入力してください。");
} else if (!PostalCodeValidator.isValidFormat(postal.trim())) {
    errors.add("郵便番号の形式が正しくありません。(例:1234567 または 123-4567)");
} else {
    String normalized = PostalCodeUtil.normalizeTo7Digits(postal);
    // normalized は必ず 7桁の数字(または null)なので、DB保存や住所検索に使える
}
Java

ここでの重要ポイントは二つです。

一つ目は、「未入力チェック」と「形式チェック」を分けている」ことです。
「入力してください」と「形式が正しくありません」は、ユーザーに伝えたい内容が違うので、
条件もメッセージも分けて書いたほうが親切です。

二つ目は、「チェックに通ったら、すぐに正規化してしまう」ことです。
以降の処理は「7桁の数字だけを扱う」前提で書けるので、
ハイフンの有無や空白を気にしなくて済みます。


「形式チェック」と「実在チェック」は別物だと理解する

郵便番号チェックユーティリティがやっているのは、
あくまで「文字列の形がそれっぽいかどうか」の判定だけです。

1234567 が形式的に正しくても、
その番号が本当に存在するかどうかは分かりません。

実在チェックをしたいなら、

郵便番号データベース(CSVなど)を持って照合する
外部の住所検索APIを叩いてみる

といった別の仕組みが必要になります。

ここで大事なのは、
「形式チェックは“明らかにおかしいものを弾くフィルタ”であって、“正しいことの保証”ではない
という感覚を持っておくことです。


まとめ:郵便番号チェックユーティリティで身につけたい感覚

郵便番号チェックは、「完璧な判定」を目指すものではなく、
「明らかにおかしいものを早めにはじくためのフィルタ」 です。

まずは、

^(\\d{7}|\\d{3}-\\d{4})$ のようなシンプルな正規表現で
「7桁」か「3桁-4桁」だけを許可する

というところから始めてみてください。

そのうえで、

PostalCodeValidator.isValidFormat で形式をチェックし、
PostalCodeUtil.normalizeTo7Digits で7桁に正規化する

という二段構えにしておくと、
入力フォームのバリデーションも、内部処理のロジックも、ぐっと書きやすくなります。

もしあなたのコードのどこかに、

String postal = request.getParameter("postalCode");
// そのままDBに保存
Java

のような箇所があれば、
そこを題材にして、ここで作った isValidFormatnormalizeTo7Digits を一度挟んでみてください。

それだけで、「明らかにおかしい郵便番号がシステムに入り込む」リスクを、かなり減らすことができます。

タイトルとURLをコピーしました