Unicodeとバリデーション
Date2026/10/08 Last Modified2026/10/08
概要
とあるETLのシステムにおいて、たびたびエラーが発生しており、聞いてみるとこんな感じだった。
「漢字を入れてるのに全角と認識されない」
「名前に記号を入れてくる人を何とかしてほしい」
起こった各事象について調べてみたら理解はできたのだが、あんまり文字コードとかはよく知らないなと感じた。
せっかくの機会なので、今後のためにも詳しく調べてみようと思った。
UnicodeとUTF-8
「文字コード」という言葉を使って、「Unicode」や「UTF-8」の話をすることが多いけれども、実際は微妙に区分が違うらしい。
| 用語 | 役割 | 例 |
|---|---|---|
| 文字集合 | どんな文字を扱うか | Unicode, JIS X 0208 |
| コードポイント | 各文字に付けた番号 | U+0041, U+3042 |
| 文字エンコーディング | 番号をどうバイト列にするか | UTF-8, Shift_JIS |
普段よく耳にする文字化けの話は「文字エンコーディング」のほう。
今回、バリデーションで範囲を区切りたいのは「文字集合」のほうだった。
文字コードという呼び方は慣習によるもので、少し広い意味を扱っていたみたい。
UnicodeとJIS水準
一つ話題に上がったのは「異体字」の扱いである。
例えば「高橋」と「髙橋」、「山崎」と「山﨑」、みたいに複数の記法がある漢字がある。
これを「JIS第〇水準」と表現することがあるが、それってそもそもUnicodeと関連があるものなんだろうか。
JISってJIS X 0208みたいな、そもそもUnicodeと別の文字集合のこと
恥ずかしながらShift_JISとJIS第〇水準という言葉に関連があることを初めて知った。
なるほど!てっきり漢検とか常用漢字みたいな、もうちょっとカジュアル寄りな話かと思ってた。
Unicodeは世界基準の文字集合なので、世界から見ると「漢字っぽいものは全部漢字」でしかない。そうなると、世界基準でみれば中国語も日本語も大体同じなのである。
実際にUnicodeの対応表を見てみると「漢字」という広い集合はあるものの、JIS水準で言えば色んな区分が混ざっている。
なので、Unicode上で「JIS第一水準の漢字のみを許可」する場合は範囲指定で綺麗に分けられるわけではない。
UTF-8を使いながらJIS第一水準の漢字のみを許可したい
実務ではこういう場面もあると思う。2つの文字集合を参照したいとき、どうするか?
イレギュラーな方を静的データとして保持するべし
基本的に1つの文字集合を使ってシステムを構築しないといけない。
仮にUTF-8を使いながら、JISの基準も入れたい場合は「JISの基準をあらかじめ取り込んでホワイトリストを作ってしまう」というのが良い。
JisX0208Level1.php みたいな感じで専用ファイルを作って、
とするのが一番簡単な実装である。
あくまでもUnicodeを維持するために、JIS X 0208の表から一部を拝借して静的データに置き換えた、ということになる。
これができるということは、Unicodeで綺麗に当てはまらない集合も、他の文字集合からとってくれば良いということがわかる。
標準的な名前のバリデーションって結局どうする?
ここまでは「JIS第一水準」など他の集合を参照できる話だったけれども、「人名」というぼんやりした境界はどうやって作っていくべきだろうか。
パッと思いつく区分は「全角文字」「人名漢字・カタカナ・ひらがな」だが、この「人名漢字」ってどう区別するのか。
まずは大まかな基準がどうなっているかを調べてみたところ、以下のようになっていた。
| 要件 | 現実的なバリデーション |
|---|---|
| 単なる表示名 | かなり広くUnicodeを許可 |
| 日本語氏名欄 | 漢字・ひらがな・カタカナ・必要な記号等 |
| 古い基幹システム連携 | JIS第1・第2水準など連携先仕様 |
| 戸籍レベルの正確性 | 戸籍統一文字/MJ文字など専用文字集合 |
具体的な範囲はわからないが、結局のところデータの取り扱い方によってずいぶん変わるので「絶対にこれ」という基準はなさそう。
例えばゲームのユーザー名なら危険な文字を除いて記号なども使えるべきだし、日本語氏名なら漢字であればとりあえず良し、古い基幹システムならUTF-8じゃないかもしれないからJISに対応するもの、戸籍は正確性が必要なので、戸籍に登録できる漢字を厳密に区分する。
ということで、まずは「どんな用途に使う?」が最初に来る。
その次は、一般的な人名漢字の分け方を調べてみた。
- ‘\p{Han}‘はどこまで?
代表的な漢字系の文字体系とされる"Han"について調べてみたところ、かなり色んな範囲をカバーしていることが分かった。
だいたいの常用漢字はU+4E00 ~ U+9FFFに入っていて、それ以外は基本的に見たことがないもの。