You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 23:52:42