I have annotation classes
annotation class Endpoint(val name: String)
@Target(AnnotationTarget.TYPE)
annotation class JsonObjectKey(val name: String)
These are used like so
@Endpoint("my-endpoint")
fun myEndpoint(): @JsonObjectKey("key") String {
return "value"
}
With a method: java.lang.reflect.Method
object representing myEndpoint
,
I am able to access the Endpoint
-Annotation, but I fail to access the JsonObjectKey
-Annotatation.
method.annotations
only contains Endpoint
method.annotatedReturnType.annotations
is empty
How to read JsonObjectKey
(key
in this scenario)?
Intention is to generate JsonObject {"key": "value"}
CodePudding user response:
Use the Kotlin reflection API!
For example, this works:
fun main() {
println(::myEndpoint.returnType.annotations)
}
@Target(AnnotationTarget.TYPE)
annotation class JsonObjectKey(val name: String)
fun myEndpoint(): @JsonObjectKey("key") String {
return "value"
}
This outputs:
[@JsonObjectKey(name=key)]
If you only have a java.lang.reflect.Method
for some reason, you can convert it to a KFunction
using kotlinFunction
:
println(someJavaMethod?.kotlinFunction?.returnType?.annotations)
It appears that annotations annotated in this position in Java:
public static @JsonObjectKey(name = "foo") String foo()
are very different from those annotated in this position in Kotlin:
fun foo(): @JsonObjectKey("key") String = ""
These seem to be two different positions. Kotlin reflection cannot see the annotation on the Java return type, and Java reflection cannot see the annotation on the Kotlin return type.
Compare how the annotations appear in the class file. For the Java method, the annotation shows up in the RuntimeVisibleTypeAnnotations
attribute:
RuntimeVisibleTypeAnnotations:
0: #23(#24=s#20): METHOD_RETURN
JsonObjectKey(
name="foo"
)
On the other hand, the Kotlin method instead has the annotation stored as part of the kotlin.Metadata
annotation:
RuntimeVisibleAnnotations:
0: #86(#87=[I#88,I#89,I#90],#91=I#92,#93=I#94,#95=[s#96],#97=[s#5,s#98,s#76,s#98,s#99,s#100,s#101,s#102])
kotlin.Metadata(
mv=[1,6,0]
k=2
xi=48
d1=["..."]
d2=["main","","myEndpoint","","LJsonObjectKey;","name","key","myproject"]
)