1
Implement Validatable and declare the rules
A class that knows its own rules implements
Validatable and returns them from validation(). Each line starts
with a property, says what null means for it, and lists its constraints:User.kt
::name required { minLength(2) } reads as the requirement: the name is required, and has at least 2
characters. ::age ifPresent { min(18) } says the age may be missing, but when it is there, it is at least 18.2
Validate
validate() runs every rule and returns a ValidationResult:validate() is a suspend function, so a rule can query a database or an API. Outside a coroutine, call
validateBlocking() instead. It runs the same rules and blocks the thread until they finish.3
Read the violations
The three rules are broken at once, and each violation has a path, a message and a code:
Show the
message to people and branch on the code in programs: codes never change with the language of the
messages.4
Or throw at the edge of your system
In a controller or a handler,
validateOrThrow() throws a ValidationException that carries the same list, so
one error handler can turn every invalid request into a response:What to read next
What null means
required, ifPresent and forbidden, the start of every rule.Nested objects
valid() follows the data, and the path follows it too.Rules across fields
One of two fields, a total that matches its items.
Every constraint
175 of them, by the type of value they check.