I'm trying to extract the value of a @JsonProperty annotation in Kotlin. The annotation is from the com.fasterxml.jackson.core dependency (version 2.18.1).
Previously, I used the @SerializedName annotation from com.google.gson.annotations with similar code, and it worked fine. However, after migrating to Jackson, the same approach no longer works. Setup
Kotlin: 2.0.0
Spring Boot: 3.4.0
Maven Dependencies:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.18.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.18.1</version>
</dependency>
Here is the SomeClass where I want to extract the @JsonProperty annotation values:
import com.fasterxml.jackson.annotation.JsonProperty
import kotlin.reflect.full.memberProperties
import kotlin.reflect.jvm.javaField
data class SomeClass(
val data: String,
@JsonProperty("somefield_A")
val name: String,
@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
}
}
}
}
The code is based on this answer. However, unlike @SerializedName, this implementation fails to retrieve the values of @JsonProperty.
I also reviewed this similar question, but I couldn't identify what I'm missing.
So my Question is: Why does the @JsonProperty annotation fail to return its value in this case, and how can I fix this?
In addition to fields, @JsonProperty
can also be applied to parameters, and this is what Kotlin chooses to apply the annotation to.
@JsonProperty
is applied to the parameter of your data class' primary constructor, not the field backing the properties. See also the end of this section in the documentation.
You should write
@field:JsonProperty("somefield_A")
instead.
Alternatively, it's also possible to find annotations on a parameter like this:
@OptIn(ExperimentalStdlibApi::class)
fun getAnnotationValues(): List<String> {
return SomeClass::class.primaryConstructor?.parameters
?.map {
it.findAnnotations(JsonProperty::class).firstOrNull()?.value
?: it.name ?: "no name"
} ?: emptyList()
}