Валидация данных в Kotlin: обзор библиотек и практические примеры
Валидация данных — один из ключевых аспектов разработки надёжных приложений. В Kotlin, благодаря его лаконичному синтаксису и мощной системе типов, процесс проверки данных может быть не только эффективным, но и выразительным. В этой статье мы рассмотрим популярные библиотеки для валидации, их возможности и приведём практические примеры кода.
Зачем нужна валидация в Kotlin?
Валидация позволяет:
- Обеспечить целостность данных перед их обработкой;
- Улучшить пользовательский опыт за счёт понятных сообщений об ошибках;
- Снизить нагрузку на базу данных и серверную логику;
- Предотвратить уязвимости, связанные с некорректным вводом.
Основные подходы к валидации
В Kotlin можно выделить три основных подхода:
- Аннотации — декларативный способ, часто используется с Jakarta Bean Validation (ранее JSR-380).
- DSL-валидация — создание валидаторов с помощью предметно-ориентированного языка (например, Konform).
- Функциональный подход — использование функций высшего порядка для композиции правил проверки.
1. Библиотека Konform
Konform — это лёгкая библиотека для валидации данных в Kotlin, которая использует DSL. Она идеально подходит для проверки объектов, полученных из JSON или форм.
Пример использования:
import konform.*
import konform.dsl.*
data class User(
val name: String,
val email: String,
val age: Int
)
fun main() {
val userValidator = validation<User> {
User::name required {
minLength(2) hint "Имя должно содержать минимум 2 символа"
maxLength(50) hint "Имя не должно превышать 50 символов"
}
User::email required {
pattern(Regex("^[\\w.-]+@[\\w.-]+\\.\\w{2,}$")) hint "Некорректный email"
}
User::age required {
range(18..120) hint "Возраст должен быть от 18 до 120 лет"
}
}
val user = User("А", "invalid-email", 17)
val result = userValidator.validate(user)
if (result is ValidationResult.Invalid) {
result.errors.forEach { (field, errors) ->
println("Поле '$field': ${errors.joinToString(", ")}")
}
} else {
println("Валидация пройдена!")
}
}
Вывод:
Поле 'name': Имя должно содержать минимум 2 символа
Поле 'email': Некорректный email
Поле 'age': Возраст должен быть от 18 до 120 лет
2. Библиотека Kotlin Validation (KValidation)
KValidation — ещё один популярный инструмент, предоставляющий как аннотации, так и DSL. Он интегрируется с Kotlin Serialization и поддерживает вложенные объекты.
Пример с аннотациями:
import io.kvalidation.annotations.*
import io.kvalidation.KValidation
@Validatable
data class Address(
@NotEmpty(message = "Улица не может быть пустой")
val street: String,
@Range(min = 1, max = 9999, message = "Номер дома должен быть от 1 до 9999")
val houseNumber: Int
)
@Validatable
data class Person(
@NotEmpty(message = "Имя обязательно")
@Length(min = 2, max = 100, message = "Имя должно содержать от 2 до 100 символов")
val name: String,
@Email(message = "Некорректный email")
val email: String,
@Valid // вложенная валидация
val address: Address
)
fun main() {
val person = Person("", "test", Address("", 0))
val violations = KValidation.validate(person)
violations.forEach { violation ->
println("${violation.propertyPath}: ${violation.message}")
}
}
3. Функциональный подход без библиотек
Если вам не нужна полноценная библиотека, можно реализовать валидацию с помощью простых функций:
data class LoginRequest(val username: String, val password: String)
sealed class ValidationError(val message: String) {
class EmptyField(field: String) : ValidationError("Поле '$field' не может быть пустым")
class TooShort(field: String, min: Int) : ValidationError("Поле '$field' должно содержать минимум $min символов")
}
typealias Validator<T> = (T) -> List<ValidationError>
fun <T> validate(value: T, vararg