Kotlin中Jackson @JsonProperty注解值无法获取的原因及解决方法
问题原因
你遇到的核心问题是Kotlin Data Class中@JsonProperty与Gson的@SerializedName注解的默认标注逻辑不同:
- Gson的@SerializedName会被Kotlin编译器自动同步到生成的Java字段上,因此通过
javaField?.getAnnotation()可以正常获取注解值; - 而Jackson的@JsonProperty默认仅标注在Data Class的构造函数参数上,并未自动复制到对应的Java字段,所以你通过
field.javaField?.getAnnotation()无法读取到注解内容。
修复方案
方案1:显式指定注解标注在字段上
在@JsonProperty前添加@field:限定符,强制让注解编译到Java字段中,原有反射代码即可正常工作:
import com.fasterxml.jackson.annotation.JsonProperty import kotlin.reflect.full.memberProperties import kotlin.reflect.jvm.javaField data class SomeClass( val data: String, @field:JsonProperty("somefield_A") val name: String, @field:JsonProperty("somefield_B") val user: String, ) { companion object { fun getAnnotationValues(): List<String> { return SomeClass::class.memberProperties.map { field -> field.javaField?.getAnnotation(JsonProperty::class.java)?.value ?: field.name } } } }
方案2:通过Kotlin反射读取构造参数注解
无需修改注解位置,直接通过Kotlin反射定位构造函数中对应属性的参数,读取其上的@JsonProperty注解:
import com.fasterxml.jackson.annotation.JsonProperty import kotlin.reflect.full.findParameterByName import kotlin.reflect.full.memberProperties import kotlin.reflect.full.primaryConstructor data class SomeClass( val data: String, @JsonProperty("somefield_A") val name: String, @JsonProperty("somefield_B") val user: String, ) { companion object { fun getAnnotationValues(): List<String> { val primaryConstructor = SomeClass::class.primaryConstructor ?: return emptyList() return SomeClass::class.memberProperties.map { prop -> primaryConstructor.findParameterByName(prop.name) ?.findAnnotation<JsonProperty>() ?.value ?: prop.name } } } }
方案3:使用Jackson官方Introspector工具(推荐)
直接利用Jackson自身的元数据解析工具,可正确识别所有Jackson支持的注解位置(字段、构造参数、getter/setter等),是最可靠的实现方式:
import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector import com.fasterxml.jackson.databind.type.TypeFactory import kotlin.reflect.full.memberProperties data class SomeClass( val data: String, @JsonProperty("somefield_A") val name: String, @JsonProperty("somefield_B") val user: String, ) { companion object { fun getAnnotationValues(): List<String> { val introspector = JacksonAnnotationIntrospector() val type = TypeFactory.defaultInstance().constructType(SomeClass::class.java) val beanDescription = introspector.introspect(type) return SomeClass::class.memberProperties.map { prop -> beanDescription.findField(prop.name)?.let { introspector.findPropertyName(it) } ?: prop.name } } } }
内容的提问来源于stack exchange,提问作者H_Braun
相关产品推荐
相关产品推荐

