I'm building a schema generator and I'm trying to get the JsonProperty
of enum values, for example, for this class:
enum class Size {
@JsonProperty("really-tall") TALL,
@JsonProperty("really-grande") GRANDE;
}
I'd like to get the list "really-tall", "really-grande"
.
How do I access the annotation of an enum? Thanks!
UPDATE:
Solution based on this reply for a generic KType
:
return (jvmErasure.java as Class<Enum<*>>)
.enumConstants
.map {
it.javaClass.getField(it.name).getAnnotation(JsonProperty::class.java)?.value // Get the JsonProperty string first if exists
?: it.name
}
Update: Additional question from OP
How do I make the first approach work for a generic KType
inline fun <reified T : Enum<T>> getJsonPropertyAnnotations() = enumValues<T>().map {
it.declaringClass
.getField(it.name)
.getAnnotation(JsonProperty::class.java)
.value
}
class SomeTest : StringSpec({
"getJsonPropertyAnnotations" {
getJsonPropertyAnnotations<Size>()
shouldBe listOf("really-tall", "really-grande")
}
})
Please note that with Kotlin 1.7, IntelliJ may show a deprecation warning with wrong replacement for declaringClass
in getJsonPropertyAnnotations
. I guess this will be sorted out in later versions. Link to related source
The following code should do what you want.
class SomeTest : StringSpec({
"getting annotation values" {
val result = enumValues<Size>().map {
it.declaringClass.getField(it.name).getAnnotation(JsonProperty::class.java).value
}
result shouldBe listOf("really-tall", "really-grande")
}
})
An alternative (less code): Add a String property to your enum class (I called it someFieldName in the below code), annotate with @get:JsonValue
, and construct each enum entry with the string value you want. @get:JsonValue
will use someFieldName instead of the enum value during serialization.
enum class Size(@get:JsonValue val someFieldName: String) {
TALL("really-tall"),
GRANDE("really-grande");
}
Same test again
class SomeTest : StringSpec({
"getting prop values" {
val result = enumValues<Size>().map {
it.someFieldName
}
result shouldBe listOf("really-tall", "really-grande")
}
})
We're using the latter approach in an ongoing project.