Bean Validation の @Pattern の仕様

2024/08/12

はじめに

今回は Java の Bean Validation の @Pattern の仕様について説明する。誤った例を使っている解説が多く、それを参照したコードをレビューで見て疲弊する日々を過しているため、世の中に正しい情報が提供されることを期待するのは諦めて自ら発信していくことにした。

先日の記事もその一環の中の一つである。

TL;DL

  • @Patternregexp で指定する正規表現の先頭に ^ と末尾に $ を付ける必要はない
  • ドキュメントを読んで仕様を確認しましょう
  • 個人のブログや Qiita、Zenn の情報を鵜呑みにしない (自己矛盾)

誤った実装

Google で Spring Boot を使ってリクエストに @Pattern アノテーションを使い正規表現でバリデーションをかける方法を検索すると次のような例をよく見る。

Loading code...

^$ の両方、もしくはいずれかを使っている例も見られるが ^<正規表現>$ という形式で @Patternregexp に正規表現を記述している。これは正しく動作するため、誤った実装ではないが ^$ を使う必要はない。

^$ をわざわざ付けている人は @Pattern の仕様を理解していない可能性がある。

Jakarta Bean Validation

Java でバリデーションを実装したい場合は、Jakarta Bean Validation に準拠したライブラリを使うのが一般的でだろう。 Jakarta Bean Validation は、JSR 303JSR 349, JSR 380 で定められた Bean Validation が移管され、 Eclipse Foundation により管理されている Bean Validation について定めた仕様である 1

Java では Jakarta Bean Validation のように仕様のみが独立して定められ、それを実装するライブラリが複数存在することがある。例えば、Jakarta Bean Validation のリファレンス実装として Hibernate Validator がある。 Hibernate Validator を使うことが多いが、Jakarta Bean Validation に準拠した実装には Apache BVal もある。

Hibernate Validator

PatternValidator

@Pattern アノテーションのバリデーションは PatternValidator で行われる。

Loading code...
org/hibernate/validator/internal/constraintvalidators/bv/PatternValidator.java

検証成功するかどうかは Mather#matches メソッドで判定される。 Matcher#matches は、文字列全体が正規表現に一致するかどうかを判定するメソッドである。一部のみが一致している場合は検証は失敗する。そのため、@Pattern アノテーションでは ^$ を使わなくても文字列全体が正規表現に一致すれば検証は成功する。

正しい (?) 実装

^$ を付けても動作としては変わらないが、ただのノイズでしかないため、不要な記述は避けるべきだろう。よって、始めに見た実装例は次のように書き換えることができる。

Loading code...

おわりに

@Patternregexp に正規表現を指定する際に ^$ を付ける必要はない。昔に書かれた記事では ^$ を使う例はないが、最近書かれた記事では ^$ を付けているものが多いように思う。

ある時点で誤った情報が書かれてしまい、ネットで見つけたコードをそのまま使う人が多いということだろう。ネットで見つけた情報を鵜呑みにせず、公式ドキュメントを読んで仕様を確認することが大切。

Footnotes

  1. Java EE と Jakarta EE については Java EE から Jakarta EE へ を参照。

SuzumiyaAobaのプロフィール画像

SuzumiyaAoba

プログラミング、技術、その他の話題について共有するブログを書いてます。 主にScala、Java、TypeScriptなどの技術について興味あり。

ScalaJavaTypeScriptReact

Buy Me A Coffee