LoginSignup
1
0

More than 1 year has passed since last update.

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

Last updated at Posted at 2020-06-17

はじめに

サロゲートペア(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を用いることで、サロゲートペアも1文字としてカウントできます。
@CustomSize(min = 1, max = 10)などと指定するとサロゲートペアでも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を渡しても大丈夫です!

1
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0