Reflectiegebaseerde validatie en mapping
Bouw een eenvoudige validator of objectmapper met annotatiegestuurde reflection.
Reflectiegebaseerde validatie en mapping is een gratis Kotlin Academy-les op CoddyKit. Dit is les 4 van 4. Je kunt 3 lessen uit dit leerpad gratis volledig lezen — daarna ontgrendelt CoddyKit PRO alle lessen, plus praktische oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Kotlin Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Kotlin Academy bevat in totaal 4 lessen.
Welk probleem lost dit patroon op?
Validatie op basis van reflectie leest tijdens runtime annotaties uit de eigenschappen van een klasse en past validatieregels automatisch toe — geen handmatige controles per veld. Dezelfde techniek vormt de basis voor ORM-mappers die objecten omzetten tussen objecten en rijen in een database.
De Validate-annotatie
Definieer een annotatie die tijdens runtime behouden blijft en op eigenschappen kan worden toegepast:
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.PROPERTY)
annotation class Validate(
val minLength: Int = 0,
val maxLength: Int = Int.MAX_VALUE,
val pattern: String = ""
)Een gegevensklasse annoteren
Pas @Validate toe op de eigenschappen van een gegevensklasse. De validator scant deze tijdens runtime:
data class UserForm(
@Validate(minLength = 2, maxLength = 50) val name: String,
@Validate(pattern = "^[\\w.]+@[\\w]+\\.[a-z]{2,}$") val email: String,
@Validate(minLength = 8) val password: String
)De validatorfunctie
Gebruik KClass.declaredMemberProperties om eigenschappen te doorlopen, annotaties te vinden en fouten te verzamelen:
fun validate(obj: Any): List<String> {
val errors = mutableListOf<String>()
for (prop in obj::class.declaredMemberProperties) {
val ann = prop.findAnnotation<Validate>() ?: continue
val value = (prop as KProperty1<Any, *>).get(obj)?.toString() ?: ""
if (value.length < ann.minLength) errors += "${prop.name}: too short"
if (value.length > ann.maxLength) errors += "${prop.name}: too long"
if (ann.pattern.isNotEmpty() && !value.matches(Regex(ann.pattern)))
errors += "${prop.name}: invalid format"
}
return errors
}De validator uitvoeren
Roep validate() aan met een willekeurig geannoteerd object. De functie retourneert een lijst met foutmeldingen; een lege lijst betekent dat het object geldig is:
val form = UserForm("A", "not-an-email", "short")
val errors = validate(form)
errors.forEach(::println)
// name: too short
// email: invalid format
// password: too shortObjecten naar kaarten omzetten met @Column
Een ander reflectiepatroon zet een object om in een Map en gebruikt een @Column-annotatie om kolomnamen op te geven:
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.PROPERTY)
annotation class Column(val name: String)
fun toMap(obj: Any): Map<String, Any?> =
obj::class.declaredMemberProperties
.mapNotNull { prop ->
val col = prop.findAnnotation<Column>() ?: return@mapNotNull null
col.name to (prop as KProperty1<Any, *>).get(obj)
}.toMap()De mapper gebruiken
Annoteer de gegevensklasse en roep toMap() aan om een kaart met kolommen als sleutels te krijgen, klaar voor een INSERT-instructie:
data class User(
@Column("user_name") val name: String,
@Column("user_email") val email: String
)
val user = User("Alice", "alice@example.com")
println(toMap(user))
// {user_name=Alice, user_email=alice@example.com}Reflectieresultaten cachen
Reflectiescans zijn duur. Cache de toewijzing van eigenschappen aan annotaties bij het opstarten met een ConcurrentHashMap waarvan de sleutels KClass zijn:
val cache = ConcurrentHashMap<KClass<*>, List<Pair<KProperty1<Any,*>, Column>>>()
fun columnsOf(klass: KClass<*>) = cache.getOrPut(klass) {
klass.declaredMemberProperties
.mapNotNull { p ->
p.findAnnotation<Column>()?.let { (p as KProperty1<Any,*>) to it }
}
}Validatie en toewijzing combineren
Je kunt meerdere annotaties op één eigenschap stapelen en ze afzonderlijk verwerken. Valideer eerst en wijs daarna toe — of doe beide in één doorgang door elk annotatietype te verzamelen:
data class Product(
@Validate(minLength = 1) @Column("product_name") val name: String,
@Column("price") val price: Double
)Beperkingen
Validatie op basis van reflectie is krachtig, maar heeft nadelen: er komt extra overhead tijdens runtime bij kijken, de werking is afhankelijk van het behouden van annotaties en fouten kunnen niet tijdens het compileren worden gevonden. Overweeg voor validatie die prestatiekritisch of veilig tijdens het compileren moet zijn in plaats daarvan door KSP gegenereerde code.
Wanneer je dit patroon gebruikt
Validatie op basis van reflectie komt goed tot zijn recht in frameworkcode die willekeurige, door gebruikers gedefinieerde klassen moet verwerken: ORM's, serializers, formulier-validators en configuratiebinders. Applicatiecode die de eigen typen beheert, gebruikt voor snelheid en duidelijkheid bij voorkeur expliciete validatie.
Korte controle
Welk beleid voor het behouden van annotaties is vereist om een validatieannotatie tijdens runtime te kunnen lezen?
Samenvatting: validatie en toewijzing op basis van reflectie
Belangrijkste punten:
- Declareer annotaties die tijdens runtime behouden blijven en op eigenschappen zijn gericht
- Gebruik
declaredMemberProperties+findAnnotationals basis voor validatie of toewijzing - Cache resultaten per
KClassom herhaalde reflectie-overhead te vermijden - Stapel meerdere annotaties op een eigenschap voor gecombineerd gedrag
- Overweeg KSP als alternatief tijdens het compileren voor prestatiekritieke paden
Leer Kotlin met een AI-tutor — gratis
Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.
- Cursussen
- 51
- Lessen
- 203
Veelgestelde vragen
Is de les “Reflectiegebaseerde validatie en mapping” gratis?
Ja — je kunt hier op het web alle 3 lessen van het leerpad Kotlin Academy, waaronder “Reflectiegebaseerde validatie en mapping”, gratis volledig lezen. Daarna ontgrendelt CoddyKit PRO alle lessen, plus interactieve oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. De cursus Kotlin Academy bevat in totaal 4 lessen.
Wat leer ik in “Reflectiegebaseerde validatie en mapping”?
Bouw een eenvoudige validator of objectmapper met annotatiegestuurde reflection. Je oefent met Kotlin Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.
Heb ik ervaring nodig om met Kotlin Academy te beginnen?
Ervaring vooraf is niet nodig. Kotlin Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 4 van 4.
Hoe lang duurt de les “Reflectiegebaseerde validatie en mapping”?
De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.
Kan ik code schrijven en uitvoeren in deze les over Kotlin Academy?
Ja. Elke les over Kotlin Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.
Alle lessen in deze cursus
- Kotlin-reflectie: KClass, KFunction, KProperty
- Aangepaste annotaties maken en targeten
- Annotaties lezen tijdens runtime
- Reflectiegebaseerde validatie en mapping