Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

[Kotlin + SpringBoot] サロゲートペア文字を含む文字列のSize Validation

はじめに

サロゲートペア(4バイトの文字)を含む文字列のValidationをしようとしたときに、サロゲートペアだけ2文字カウントされてうまくいかなかったので、これも1文字カウントするカスタムアノテーションを作ってみました。

コード

Constraint(validatedBy = [CustomSizeValidator::class])
@Target(AnnotationTarget.FIELD)
@Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented
@ReportAsSingleViolation
annotation class CustomSize(
        val message: String = "Size is invalid",
        val groups: Array<KClass<out Any>> = [],
        val payload: Array<KClass<out Payload>> = [],
        val max: Int = Int.MAX_VALUE,
        val min: Int = 0
)

class CustomSizeValidator : ConstraintValidator<CustomSize, String> {
    private var maxSize: Int by Delegates.notNull()
    private var minSize: Int by Delegates.notNull()

    override fun initialize(customSize: CustomSize) {
        maxSize = customSize.max
        minSize = customSize.min
    }

    override fun isValid(value: String?, context: ConstraintValidatorContext?): Boolean {
        return (value?.codePointCount(0, value.length) in minSize..maxSize)
    }
}

annotation classのところはお作法?にしたがいます。
max, minのデフォルト値はinitializeで初期化するため、初期化遅延する必要があります。
しかしプリミティブ型の変数はlateinitが使えないので、

private var maxSize: Int by Delegates.notNull()
private var minSize: Int by Delegates.notNull()

としています。
codePointCountを用いることで、4バイト文字も1文字としてカウントできます。
@CustomSize(min = 1, max = 10)などと指定すると4バイト文字でも1文字扱いでValidationをかけることができます。

使用例

data class Hoge(
    @field:NotNull
    val id: Int?

    @field:NotEmpty
    @field:CustomSize(max = 20)
    val name: String?,
)
...
fun hogeController(@RequestBody @Valid book : Book){
    ...
}

細かなところは省きますが、これでhogeControllerに𠀋𠀋𠀋𠀋𠀋𠀋𠀋𠀋𠀋𠀋𠀋𠀋𠀋𠀋𠀋𠀋𠀋𠀋𠀋𠀋こんなサロゲートペアの文字20個を含むHogeを渡しても大丈夫です!

syumiwohossu
サーバサイドエンジニア始めました。 since 2020/04/01
yumemi
みんなが知ってるあのサービス、実はゆめみが作ってます。スマホアプリ/Webサービスの企画・UX/UI設計、開発運用。Swift, Kotlin, PHP, Vue.js, React.js, Node.js, AWS等エンジニア・クリエイターの会社です。Twitterで情報配信中https://twitter.com/yumemiinc
http://www.yumemi.co.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away