Quando uma classe inclui uma propriedade que é uma classe de valor inline, Jackson ignora todas as anotações anexadas a qualquer campo da classe envolvente. Exemplo mínimo reproduzível:
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
data class MyDataClass(val value: String)
@JvmInline
value class MyInlineClass(val value: String)
data class ClassUsingMyDataClass(
@JsonProperty("fred")
val myInlineClassField: MyDataClass,
@JsonProperty("barney")
val myStringField: String
)
data class ClassUsingMyInlineClass(
@JsonProperty("fred")
val myInlineClassField: MyInlineClass,
@JsonProperty("barney")
val myStringField: String
)
fun main() {
val objectMapper = jacksonObjectMapper()
// Prints {"fred":{"value":"one"},"barney":"two"} as expected
println(objectMapper.writeValueAsString(ClassUsingMyDataClass(MyDataClass("one"), "two")))
// Prints {"myInlineClassField":"one","myStringField":"two"}, why doesn't it use fred and barney?
println(objectMapper.writeValueAsString(ClassUsingMyInlineClass(MyInlineClass("one"), "two")))
}
Existe uma maneira de fazer @JsonProperty
funcionar novamente depois de incluir um campo cujo tipo é uma classe de valor inline?
Estou usando Jackson 2.18.2 e Kotlin 2.1.10.
A
@JsonProperty
anotação está sendo aplicada aos parâmetros do construtor primário, simplesmente porque pode ser. Veja a última parte desta seção da documentação para a precedência de onde aplicar uma anotação quando múltiplos alvos de anotação são aplicáveis.Tudo isso funciona bem com um regular
data class
- Jackson pode detectar essas anotações nos parâmetros do construtor.No entanto, uma vez que você usa uma classe inline como um parâmetro construtor, há dois construtores sendo gerados. Em Java, eles ficariam assim:
As
JsonProperty
anotações são adicionadas apenas à segunda sobrecarga. Não tenho certeza se esse comportamento é intencional. Este é um relatório de bug relacionado no YouTrack.De qualquer forma, para que isso funcione, você deve apenas marcar os campos com a anotação.
O Kotlin também gerará um getter para
myInlineClassField
o qual tem um nome mutilado (veja o porquê aqui ). Isso confunde um pouco o Jackson e faz com que ele escreva uma propriedade JSON extra para o getter, então você precisa doJsonIgnore
getter.