Data Validation in Kotlin: Overview of Libraries and Practical Examples
Data validation is one of the key aspects of developing reliable applications. In the Kotlin ecosystem, there are several powerful libraries that allow you to declaratively describe validation rules, avoiding cumbersome conditional constructs. In this article, we will look at three popular tools: Konad, Valiktor, and Kvalidation. You will learn how they work and see code examples for real-world tasks.
1. Konad — Functional Validation
Konad (Kotlin Validation) uses the concept of monads and functional programming. Instead of throwing exceptions, the library returns Validated<E, A>, where E is the error type and A is the successful value. This allows accumulating errors and handling them without side effects.
Installation
// build.gradle.ktsdependencies { implementation("io.github.mkobit:konad:0.3.0")}Usage Example
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(", ")}") }}Advantages of Konad:
- Pure functional style without exceptions
- Accumulation of all validation errors
- Composition of validators
2. Valiktor — Declarative Validation with Fluent API
Valiktor offers an intuitive DSL for describing rules. The library supports nested objects, collections, and custom error messages. It is one of the most popular tools for Kotlin.
Installation
// build.gradle.ktsdependencies { implementation("org.valiktor:valiktor-core:0.12.0")}Example with Nested Objects
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}") } }}Features of Valiktor:
- Full support for nested objects and lists
- Localized error messages
- Integration with Spring Boot and Ktor
3. Kvalidation — Modular Annotation-Based Validation
Kvalidation (formerly Koptional) provides both an annotation-based and a programmatic approach. The library is especially convenient for validating input data in REST APIs.
Installation
// build.gradle.ktsdependencies { implementation("com.willowtreeapps:kvalidation:1.0.0")}Example with Annotations
import com.willowtreeapps.kvalidation.annotations.*import com.willowtreeapps.kvalidation.Validator
data class Product( @field:NotBlank(message = "Pro Also in library
HTTP Client for JavaScript (Node.js): Top Libraries 2025
JWT tokens in Rust: libraries and authentication implementation
Caching in Kotlin: Redis, Caffeine and Ehcache — A Complete Guide
CLI frameworks for Kotlin: creating console applications
Reflect-Metadata TypeScript: Complete Guide with Examples