Валидация данных в Kotlin: обзор библиотек и практические примеры
Валидация данных — один из ключевых аспектов разработки надёжных приложений. В экосистеме Kotlin существует несколько мощных библиотек, которые позволяют декларативно описывать правила проверки, избегая громоздких условных конструкций. В этой статье мы рассмотрим три популярных инструмента: Konad, Valiktor и Kvalidation. Вы узнаете, как они работают, и увидите примеры кода для реальных задач.
1. Konad — функциональная валидация
Konad (Kotlin Validation) использует концепцию монад и функционального программирования. Вместо выбрасывания исключений библиотека возвращает Validated<E, A>, где E — тип ошибки, а A — успешное значение. Это позволяет накапливать ошибки и обрабатывать их без side-эффектов.
Установка
// build.gradle.kts
dependencies {
implementation("io.github.mkobit:konad:0.3.0")
}
Пример использования
import konad.*
data class User(val name: String, val age: Int)
fun validateUser(user: User): Validated<String, User> {
return Validated.valid(user)
.validate { it.name.isNotBlank() } { "Name cannot be blank" }
.validate { it.age in 18..99 } { "Age must be between 18 and 99" }
}
fun main() {
val user = User("Alice", 25)
val result = validateUser(user)
when (result) {
is Valid -> println("Valid user: ${result.value}")
is Invalid -> println("Errors: ${result.errors.joinToString(", ")}")
}
}
Преимущества Konad:
- Чистый функциональный стиль без исключений
- Накапливание всех ошибок валидации
- Композиция валидаторов
2. Valiktor — декларативная валидация с fluent API
Valiktor предлагает интуитивно понятный DSL для описания правил. Библиотека поддерживает вложенные объекты, коллекции и кастомные сообщения об ошибках. Это один из самых популярных инструментов для Kotlin.
Установка
// build.gradle.kts
dependencies {
implementation("org.valiktor:valiktor-core:0.12.0")
}
Пример с вложенными объектами
import org.valiktor.*
import org.valiktor.functions.*
data class Address(val city: String, val zip: String)
data class Person(val name: String, val email: String, val address: Address)
fun validatePerson(person: Person) {
validate(person) {
validate(Person::name).isNotBlank().hasSize(min = 2, max = 50)
validate(Person::email).isEmail()
validate(Person::address) {
validate(Address::city).isNotBlank()
validate(Address::zip).matches("\\d{5}".toRegex())
}
}
}
fun main() {
val person = Person("", "invalid-email", Address("", "123"))
try {
validatePerson(person)
} catch (e: ConstraintViolationException) {
e.constraintViolations.forEach { violation ->
println("${violation.property}: ${violation.message}")
}
}
}
Особенности Valiktor:
- Полная поддержка вложенных объектов и списков
- Локализованные сообщения об ошибках
- Интеграция с Spring Boot и Ktor
3. Kvalidation — модульная валидация на основе аннотаций
Kvalidation (ранее Koptional) предоставляет как аннотационный, так и программный подход. Библиотека особенно удобна для проверки входных данных в REST API.
Установка
// build.gradle.kts
dependencies {
implementation("com.willowtreeapps:kvalidation:1.0.0")
}
Пример с аннотациями
import com.willowtreeapps.kvalidation.annotations.*
import com.willowtreeapps.kvalidation.Validator
data class Product(
@field:NotBlank(message = "Product name is required")
val name: String,
@field:Min(0) @field:Max(10000)
val price: Double,
@field:Pattern(regex = "^[A-Z]{2}\\d{4}$", message = "Invalid product code")
val code: String
)
fun main() {
val product = Product("", -10.0, "invalid")
val errors = Validator.validate(product)
if (errors.isNotEmpty()) {
errors.forEach { (field, messages) ->
println("$field: ${messages.joinToString(", ")}")
}
} else {
println("Product is valid")
}
}
Ключевые возможности Kvalidation:
- Поддержка JSR-380 подобных аннотаций
-
Также в библиотеке
Рекомендаций