Reputation: 1800
I am trying to get all the "Keys" of annotations for use later, I am initializing the value like this:
private val wgKeys = SpecialRequestContext::class.members.associate { m ->
m.name to run {
val headerAnnotation = m.annotations.find { a -> a is Header } as? Header
headerAnnotation?.key
}
}
Unfortunately, the result is a Map with name for keys (correct), but all the values are null.
While debugging I see that m.annotations
has no values.
Are annotations not available at this step?
Update: The minimum code to demonstrate this is here, unfortunately Kotlin playground cannot do reflection though:
@Target(AnnotationTarget.VALUE_PARAMETER)
annotation class Header(val key: String)
data class SpecialRequestContext(
@Header("BK-Correlation-Id") val correlationId: String? = null,
@Header("BK-Origin") val origin: String? = null,
@Header("BK-Origin-City") val originCity: String? = null,
)
fun main() {
println(wgKeys.count())
println(wgKeys["origin"])
}
private val wgKeys = SpecialRequestContext::class.members.associate { m ->
m.name to run {
val headerAnnotation = m.annotations.find { a -> a is Header } as? Header
headerAnnotation?.key
}
}
Upvotes: 1
Views: 1474
Reputation: 271355
Notice:
@Target(AnnotationTarget.VALUE_PARAMETER)
This means that the annotation is applied to the constructor parameters, not the properties. You won't find them on the properties.
To find them on the properties, you can change it to:
@Target(AnnotationTarget.PROPERTY)
If you need them applied to the parameters for some reason, you can find them like this:
private val wgKeys = SpecialRequestContext::class.primaryConstructor!!.parameters.associate { p ->
p.name to p.findAnnotation<Header>()?.key
}
Upvotes: 1
Reputation: 10703
I'm sure there's a better way of doing this, but basically you need to:
A (rough) example:
annotation class Annotation1(val key1: String, val key2: Int)
annotation class Annotation2(val key3: String, val key4: Int)
@Annotation1(key1 = "value1", key2 = 2)
@Annotation2(key3 = "value3", key4 = 4)
class MyClass
fun main() {
val myClassAnnotations = MyClass::class.annotations
val propertiesByAnnotation =
myClassAnnotations.associateWith { (it.annotationClass as KClass<Annotation>).declaredMemberProperties }
val keyValuePerAnnotation = propertiesByAnnotation.map { (annotation, properties) ->
annotation.annotationClass.simpleName!! to properties.map { property ->
property.name to property.get(annotation)
}
}
println(keyValuePerAnnotation)
}
This prints a list of pairs, where the first item is the annotation name and the second item is a list of key-value pairs for each of the annotation's properties. The output for that example is:
[(Annotation1, [(key1, value1), (key2, 2)]), (Annotation2, [(key3, value3), (key4, 4)])]
Upvotes: 1