Home > Software engineering >  How to read kotlin annotation
How to read kotlin annotation

Time:06-10

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"]
    )
  • Related