Declarative data validation with composable rules and structured errors
implementation com.philiprehberger:schema-validatorDeclarative data validation with composable rules and structured errors.
implementation("com.philiprehberger:schema-validator:0.2.0")
<dependency>
<groupId>com.philiprehberger</groupId>
<artifactId>schema-validator</artifactId>
<version>0.2.0</version>
</dependency>
import com.philiprehberger.schemavalidator.*
data class User(val name: String, val email: String, val age: Int)
val userSchema = schema<User> {
field("name", User::name) { required(); minLength(2) }
field("email", User::email) { required(); email() }
field("age", User::age) { range(13..120) }
}
when (val result = userSchema.validate(user)) {
is ValidationResult.Valid -> process(result.value)
is ValidationResult.Invalid -> result.errors.forEach { println("${it.field}: ${it.message}") }
}
data class DateRange(val start: Int, val end: Int)
val dateSchema = schema<DateRange> {
field("start", DateRange::start) { range(1..365) }
field("end", DateRange::end) { range(1..365) }
crossField("start must be before end") { it.start < it.end }
}
data class ContactForm(val type: String, val email: String)
val formSchema = schema<ContactForm> {
field("type", ContactForm::type) { required() }
conditionalField("email", ContactForm::email, { it.type == "email" }) {
required()
email()
}
}
val baseSchema = schema<User> { field("name", User::name) { required() } }
val extendedSchema = schema<User> { field("email", User::email) { email() } }
val fullSchema = baseSchema.compose(extendedSchema)
| Function / Class | Description |
|---|---|
schema<T> { } | Build a validation schema |
field(name, getter) { } | Add field validation rules |
required() | Field must not be null/blank |
minLength(n) / maxLength(n) | String length constraints |
range(intRange) | Number range constraint |
email() | Basic email format check |
matches(regex) | Regex pattern match |
custom(message) { predicate } | Custom validation rule |
crossField(message) { } | Cross-field validation |
conditionalField(name, getter, condition) { } | Conditional field validation |
Schema.compose(other) | Combine two schemas |
minLength(n, message) | Min length with custom error |
maxLength(n, message) | Max length with custom error |
ValidationResult.Valid / Invalid | Sealed result type |
./gradlew test
./gradlew build
If you find this project useful: