Usage of Jackson @JsonProperty annotation for kotlin data classes

Mike picture Mike · Dec 26, 2017 · Viewed 27.6k times · Source

kotlin 1.2.10 jackson-module-kotlin:2.9.0

I have the following data class in kotlin:

data class CurrencyInfo(
        @JsonProperty("currency_info") var currencyInfo: CurrencyInfoItem?
)

@JsonInclude(JsonInclude.Include.NON_NULL)
data class CurrencyInfoItem(
        @JsonProperty("iso_4217") var iso4217: String?,
        @JsonProperty("name") var name: String?,
        @JsonProperty("name_major") var nameMajor: String?,
        @JsonProperty("name_minor") var nameMinor: String?,
        @JsonProperty("i_ma_currency") var iMaCurrency: Int?,
        @JsonProperty("i_merchant_account") var iMerchantAccount: Int?,
        @JsonProperty("i_x_rate_source") var iXRateSource: Int?,
        @JsonProperty("base_units") var baseUnits: Double?,
        @JsonProperty("min_allowed_payment") var minAllowedPayment: Int?,
        @JsonProperty("decimal_digits") var decimalDigits: Int?,
        @JsonProperty("is_used") var isUsed: Boolean?
)

When I try to deserialize this data class I get the following:

{"currency_info":{"iso_4217":"CAD","name":"Canadian Dollar","imerchantAccount":0,"ixrateSource":2}}

As you can see, the last two options were deserialized incorrectly. This issue could be solved by adding directly annotation to getter @get:JsonProperty. However, according to jackson docs @JsonProperty should be assigned to getters/setters/fields

So, I want to ask is there a reliable way to annotate property for jackson in kotlin to have correct serialization/deserialization (moreover all my data classes are autogenerated, so it would be hard to create some two/three lines annotations, separately for getter and setter)

Otherwise, could this issue be resolved by some jackson settings?

According to answers below, the following works for me

private val mapper = ObjectMapper().registerKotlinModule()
.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY)
.setVisibility(PropertyAccessor.CREATOR, JsonAutoDetect.Visibility.NONE)
.setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE)
.setVisibility(PropertyAccessor.SETTER, JsonAutoDetect.Visibility.NONE)
.setVisibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.NONE)

Answer

SimY4 picture SimY4 · Dec 27, 2017

@JsonProperty annotations in your code are all put on private fields within your data class and by default Jackson doesn't scan private fields for annotations. You have to instruct it to do otherwise by putting @JsonAutoDetect annotation:

@JsonAutoDetect(fieldVisibility = Visibility.ANY)
data class CurrencyInfo(
    @JsonProperty("currency_info") var currencyInfo: CurrencyInfoItem?
)

or alternatively you can move your annotations on accessor methods:

data class CurrencyInfo(
    @get:JsonProperty("currency_info") var currencyInfo: CurrencyInfoItem?
)