Zenn
🐤

【Spring Boot(kotlin)】バリデーションを自作する

2024/12/23に公開

はじめに

KotlinのAnnotationsを読んでいて、annotation classを使って何かアウトプットしたいと思いこの記事を書いています。
日本の電話番号のフォーマットをチェックするためのカスタムバリデーションを作成してみました。

作成したもの

@MustBeDocumented
@Target(AnnotationTarget.FIELD)
@Retention(AnnotationRetention.RUNTIME)
@Constraint(validatedBy = [JapanesePhoneNumberValidator::class])
annotation class JapanesePhoneNumber(
    val message: String = "有効な日本の電話番号ではありません", // エラーメッセージ
    val groups: Array<KClass<*>> = [],                    // バリデーションをグループ化する際に使用
    val payload: Array<KClass<out Payload>> = []          // バリデーションの追加情報(エラーレベルなど)を指定する際に使用
)

class JapanesePhoneNumberValidator : ConstraintValidator<JapanesePhoneNumber, String> {
    override fun isValid(value: String?, context: ConstraintValidatorContext?): Boolean {
        if (value == null) return true
        return value.matches(Regex("^0[789]0-[0-9]{4}-[0-9]{4}$"))
    }
}
使用例
@JapanesePhoneNumber
val phoneNumber: String

解説

アノテーションクラス

@Target

  • どこにアノテーションを付与するかを決める
  • AnnotationTarget.CLASSAnnotationTarget.FUNCTIONなど様々な指定ができます(10種類以上あります)

@Retention

  • アノテーションがどのタイミングまで保持されるかを指定できる
claudeに聞いてみた結果
AnnotationRetention.SOURCE  // ソースコードレベルでのみ保持(コンパイル時に破棄)
AnnotationRetention.BINARY // コンパイルされたクラスファイルまで保持(リフレクションでは参照不可)
AnnotationRetention.RUNTIME // 実行時まで保持(リフレクションで参照可能)

@Constraint

  • validatedByにバリデーションロジックを実装したクラスの指定ができる

バリデーションクラス

JapanesePhoneNumberValidator

  • ConstraintValidatorというinterfaceのisValidをオーバーライドすることで、その中にバリデーションロジックを書くことができる

まとめ

SpringBootで開発しているとjakartaやHibernateのバリデーションを使用することが多いと思うのですが、特殊なフォーマットチェックなどが必要な場合は、カスタムバリデーションを自作することで柔軟に対応できることやアノテーションクラスについても学びが得られました。
(今回は正規表現だけで済むシンプルなケースだったので、自作せずとも@Patternでも対応はできると思います)

余談

今回は正規表現で携帯電話番号のフォーマットチェックを実装しましたが、もっと正確に電話番号バリデーションかけたい場合はgoogleが出しているlibphonenumberというライブラリがあるので、それを使っても良いのかなと思いました。

Discussion

ログインするとコメントできます