Reputation: 6792
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
}
Upvotes: 1
Views: 1252
Reputation: 8909
Here's a Kotlin implementation of the technique suggested by user @aSemy.
It's an extension function on ObjectMapper for asking the mapper how it would serialize the values of an enum. This is more robust that just inspecting the @JsonProperty
annotation, since it works with @JsonValue
as well as any custom annotation introspectors registered with the mapper.
inline fun <reified T : Enum<T>> ObjectMapper.enumValues() : List<String> {
return convertValue(
kotlin.enumValues<T>(),
jacksonTypeRef<List<String>>()
)
}
Usage:
println(jsonMapper().enumValues<Size>())
Upvotes: 0
Reputation: 11339
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.
Upvotes: 1