はじめに 「郵便番号検証」は“ゆらぎを受け止めて、きっちり7桁にそろえる”仕事
郵便番号入力って、一見シンプルに見えますよね。
「7桁の数字でしょ?」で終わりそうですが、実務ではそうはいきません。
「1234567」とハイフンなしで入れる人もいれば、
「123-4567」とハイフン付きで入れる人もいる。
中には「123−4567」と全角で入れてくる人もいます。
業務で本当にやりたいことは、
「ユーザーの入力のゆらぎを受け止めて、内部では“正しい7桁の数字”として扱う」
ことです。
ここでは、初心者向けに、
郵便番号の基本ルール
正規表現を使った形式チェック
ハイフン・全角数字を吸収して“7桁に正規化”するユーティリティ
「検証」と「正規化」を分けて設計する考え方
を、例題付きで丁寧に解説していきます。
郵便番号の基本ルールをおさえる
日本の郵便番号の形式
日本の郵便番号は、基本的に「7桁の数字」です。
よく見る表記は「3桁-4桁」、つまり「123-4567」の形です。
なので、機械的なルールとしては、
「数字が7桁あること」
「(あれば)ハイフンの位置は3桁目の後だけ」
この2つを押さえておけば、実務的には十分です。
一番シンプルな「形式チェック」 正規表現で書いてみる
ハイフンあり・なし両方を許可するパターン
まずは、「入力された文字列が郵便番号として“形式的に”正しいか」を見るところから始めます。
ハイフンあり・なし両方を許可する正規表現は、こんな感じで書けます。
using System.Text.RegularExpressions;
public static class PostalCodeValidator
{
// 1234567 または 123-4567 を許可
private static readonly Regex PostalCodeRegex =
new Regex(@"^\d{3}-?\d{4}$", RegexOptions.Compiled);
public static bool IsValidFormat(string? value)
{
if (string.IsNullOrWhiteSpace(value))
{
return false;
}
return PostalCodeRegex.IsMatch(value.Trim());
}
}
C#^\d{3}-?\d{4}$ の意味をかみ砕くと、こうなります。
先頭から数字3桁
そのあとにハイフンが「あるかもしれない」(-?)
最後に数字4桁
全体で終わり
つまり、「1234567」か「123-4567」だけを許可するパターンです。
動作例で確認する
Console.WriteLine(PostalCodeValidator.IsValidFormat("1234567")); // true
Console.WriteLine(PostalCodeValidator.IsValidFormat("123-4567")); // true
Console.WriteLine(PostalCodeValidator.IsValidFormat("1234-567")); // false
Console.WriteLine(PostalCodeValidator.IsValidFormat("12-34567")); // false
Console.WriteLine(PostalCodeValidator.IsValidFormat("abc-4567")); // false
Console.WriteLine(PostalCodeValidator.IsValidFormat("")); // false
C#ここまでで、「半角数字+ハイフン」の世界では、形式チェックができるようになりました。
実務で必須になる「正規化」 ハイフンや全角数字を吸収する
ユーザー入力は“きれい”ではない前提で考える
現実の入力は、こんな感じでバラバラです。
「1234567」
「123-4567」
「1234567」
「123−4567」
これらを全部、「内部では 1234567 のような7桁の半角数字」にそろえたい。
そのために必要なのが「正規化(ノーマライズ)」です。
数字だけを抜き出して7桁かどうかを見る
一番シンプルで実務的なやり方は、
「文字列から数字だけを抜き出す → 7桁ならOK」
という考え方です。
using System;
using System.Linq;
public static class PostalCodeNormalizer
{
public static string NormalizeToDigits(string? value)
{
if (string.IsNullOrWhiteSpace(value))
{
return string.Empty;
}
// 全角数字が来る可能性も考えて、いったん全角→半角してから数字だけ抜く、という設計もアリ
// ここではまず「半角数字だけ」を対象にしたシンプル版を書きます。
var digits = new string(value.Where(char.IsDigit).ToArray());
return digits;
}
public static bool TryNormalize7Digits(string? value, out string normalized)
{
normalized = NormalizeToDigits(value);
if (normalized.Length != 7)
{
return false;
}
return true;
}
}
C#NormalizeToDigits は、「文字列から数字だけを拾い集めて返す」メソッドです。TryNormalize7Digits は、「数字だけにしてみて、7桁なら true+正規化済み値を返す」というユーティリティです。
動作例
void Test(string? input)
{
if (PostalCodeNormalizer.TryNormalize7Digits(input, out var normalized))
{
Console.WriteLine($"{input} -> OK: {normalized}");
}
else
{
Console.WriteLine($"{input} -> NG");
}
}
Test("1234567"); // 1234567 -> OK: 1234567
Test("123-4567"); // 123-4567 -> OK: 1234567
Test("1234-567"); // 1234-567 -> NG
Test("abc123-4567"); // abc123-4567 -> OK: 1234567(ここを許すかどうかは要件次第)
C#ここで重要なのは、「数字以外は全部捨てる」という挙動です。
「abc123-4567」も「1234567」として通ってしまうので、
これを許すかどうかは要件次第になります。
全角数字・全角ハイフンも考慮したい場合
全角→半角変換と組み合わせる
日本語環境だと、「123−4567」のような全角入力もよくあります。
これをきちんと扱うには、「全角→半角変換」と組み合わせるのが現実的です。
ここでは、簡易的に「全角数字と全角ハイフンだけ」を半角に寄せる例を示します。
public static class ZenkakuToHankakuUtil
{
public static string ToHalfWidthDigitsAndHyphen(string value)
{
if (string.IsNullOrEmpty(value))
{
return value;
}
var chars = value.ToCharArray();
for (int i = 0; i < chars.Length; i++)
{
char c = chars[i];
// 全角数字(0〜9)
if (c >= '0' && c <= '9')
{
chars[i] = (char)('0' + (c - '0'));
}
// 全角ハイフンっぽいもの(ー、−、― など)を半角ハイフンに寄せる例
else if (c == 'ー' || c == '−' || c == '―' || c == '-')
{
chars[i] = '-';
}
}
return new string(chars);
}
}
C#これを郵便番号の正規化と組み合わせます。
public static class PostalCodeNormalizer
{
public static bool TryNormalize7DigitsFlexible(string? value, out string normalized)
{
normalized = string.Empty;
if (string.IsNullOrWhiteSpace(value))
{
return false;
}
// まず全角数字・全角ハイフンを半角に寄せる
string half = ZenkakuToHankakuUtil.ToHalfWidthDigitsAndHyphen(value);
// そのうえで数字だけを抜き出す
string digits = new string(half.Where(char.IsDigit).ToArray());
if (digits.Length != 7)
{
return false;
}
normalized = digits;
return true;
}
}
C#動作例
void TestFlexible(string? input)
{
if (PostalCodeNormalizer.TryNormalize7DigitsFlexible(input, out var normalized))
{
Console.WriteLine($"{input} -> OK: {normalized}");
}
else
{
Console.WriteLine($"{input} -> NG");
}
}
TestFlexible("1234567"); // OK: 1234567
TestFlexible("123-4567"); // OK: 1234567
TestFlexible("1234567"); // OK: 1234567
TestFlexible("123−4567"); // OK: 1234567
TestFlexible("abc123−4567"); // OK: 1234567(ここを許すかどうかは要件次第)
C#ここまでやると、「半角/全角」「ハイフンあり/なし」のゆらぎをかなり吸収できます。
「検証」と「正規化」を分けて設計する
形式だけ見るメソッドと、正規化までやるメソッド
実務で長く使うことを考えると、
「入力が“きれいな形式かどうか”だけをチェックするメソッド」
「多少汚くても、7桁に正規化できるかどうかを見るメソッド」
を分けておくと、呼び出し側の意図がはっきりします。
例えば、こんな構成です。
public static class PostalCodeUtil
{
// 1. きれいな形式(1234567 or 123-4567)かどうか
public static bool IsCleanFormat(string? value)
=> PostalCodeValidator.IsValidFormat(value);
// 2. ゆらぎを許容して7桁に正規化できるかどうか
public static bool TryNormalize(string? value, out string normalized)
=> PostalCodeNormalizer.TryNormalize7DigitsFlexible(value, out normalized);
}
C#画面やAPI側では、要件に応じて使い分けます。
「入力欄では“きれいな形式”だけ許可したい」なら IsCleanFormat を使う。
「バッチ処理で既存データをできるだけ救いたい」なら TryNormalize を使う。
こうしておくと、「どこまでゆらぎを許すか」を呼び出し側で選べるようになります。
まとめ 「郵便番号検証ユーティリティ」は“人間のゆらぎを受け止めて、機械に優しい7桁にそろえるフィルタ”
郵便番号検証は、「7桁の数字かどうか」を見るだけでは足りません。
実務で本当に効いてくるのは、
ハイフンあり・なしの両方を受け止める
全角数字・全角ハイフンも現実的に扱う
数字だけを抜き出して7桁に正規化する
「形式チェック」と「正規化」を分けて設計する
というあたりです。
ここまで理解できれば、「とりあえず ^\d{7}$ でチェックしている」段階から一歩進んで、
“ユーザー入力のゆらぎを受け止めつつ、内部ではきっちり7桁にそろえる”
業務・実務で本当に使える C# の郵便番号検証ユーティリティを、自分の手で設計・実装できるようになっていきます。
