【问题标题】:How to get Jackson JsonProperty of enum values in Kotlin?如何在 Kotlin 中获取枚举值的 Jackson JsonProperty?
【发布时间】:2022-08-19 01:45:37
【问题描述】:
我正在构建一个模式生成器,并且我正在尝试获取枚举值的JsonProperty,例如,对于此类:
enum class Size {
@JsonProperty(\"really-tall\") TALL,
@JsonProperty(\"really-grande\") GRANDE;
}
我想得到名单\"really-tall\", \"really-grande\"。
如何访问枚举的注释?
谢谢!
更新:
基于此reply 的通用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
}
标签:
kotlin
enums
jackson
annotations
【解决方案1】:
更新:来自 OP 的附加问题
如何使第一种方法适用于通用 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")
}
})
请注意,在 Kotlin 1.7 中,IntelliJ 可能会显示弃用警告,并在 getJsonPropertyAnnotations 中错误地替换 declaringClass。我想这将在以后的版本中得到解决。 Link to related source
下面的代码应该做你想做的事。
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")
}
})
另一种选择(更少的代码):在枚举类中添加一个 String 属性(我在下面的代码中将其称为 someFieldName),使用 @get:JsonValue 进行注释,并使用所需的字符串值构造每个枚举条目。 @get:JsonValue 在序列化过程中将使用 someFieldName 而不是枚举值。
enum class Size(@get:JsonValue val someFieldName: String) {
TALL("really-tall"),
GRANDE("really-grande");
}
再次进行相同的测试
class SomeTest : StringSpec({
"getting prop values" {
val result = enumValues<Size>().map {
it.someFieldName
}
result shouldBe listOf("really-tall", "really-grande")
}
})
我们在一个正在进行的项目中使用后一种方法。
【解决方案2】:
这是 ObjectMapper 上的一个扩展函数,用于询问映射器如何序列化枚举的值。这比仅检查 @JsonProperrty 注释更加健壮,因为它可以与 @JsonValue 以及在映射器中注册的任何自定义注释内省器一起使用。
inline fun <reified T : Enum<T>> ObjectMapper.enumValues() : List<String> {
return convertValue(
kotlin.enumValues<T>(),
jacksonTypeRef<List<String>>()
)
}
用法:
println(jsonMapper().enumValues<Size>())