Description
Describe the bug
We have a json parsing test that is failing with 1.8.20-Beta but passes with 1.8.10.
To Reproduce
More info below but you can probably reproduce by running kotlin 1820-Beta and deserialising a class using @JsonAlias
Expected behavior
It should not fail.
Versions
Kotlin: 1.8.20-Beta
Jackson-module-kotlin: 2.14.2
Jackson-databind: 2.14.2
Additional context
We have a custom value class (de)serializer to "transparently" deserialise ie it will deserialize the 'wrapped' object then reflectively call the value class constructor . The 'wrapped' model in this particular test however has @JsonAlias annotation on a field.
When we test with the actual field name amount
, the test passes. When the json uses the alias instead, it fails.
Our value class deserializer:
private class ValueClassDeserializer<T : Any>(kls: KClass<T>) :
StdDelegatingDeserializer<T>(ValueConstructorConverter(kls)) {
override fun withDelegate(
converter: Converter<Any, T>,
delegateType: JavaType,
delegateDeserializer: JsonDeserializer<*>,
) = StdDelegatingDeserializer(converter, delegateType, delegateDeserializer)
}
private class ValueConstructorConverter<T : Any>(private val kls: KClass<T>) : Converter<Any?, T> {
private val ctor = kls.primaryConstructor!!
private val paramType = ctor.parameters.single().type.javaType
override fun convert(value: Any?): T = ctor.call(value)
override fun getInputType(typeFactory: TypeFactory): JavaType = typeFactory.constructType(paramType)
override fun getOutputType(typeFactory: TypeFactory): JavaType = typeFactory.constructType(kls.java)
}
The models:
@JvmInline
value class AmountInCents(val value: BigInteger) : Comparable<AmountInCents> { ... }
class MoneyInCents(
@field:JsonAlias("amountInCents") val amount: AmountInCents,
val currency: Currency,
) {
companion object {
fun ZeroIn(currency: Currency) = MoneyInCents(AmountInCents.Zero, currency)
}
}
@JvmInline
value class Savings(val value: MoneyInCents) {
inline val amount get() = value.amount
inline val currency get() = value.currency
}
The test:
@Nested inner class SavingsTest(@Autowired private val mapper: JacksonTester<Savings>) {
@Test
fun testAmount() {
val result = mapper.parse("""{"amount" : 1500, "currency": "AED"}""")
assertNotNull(result.`object`) {
assert(it.amount == AmountInCents(1500))
assert(it.currency == Currency.AED)
}
}
@Test
fun testAmountInCents() {
val result = mapper.parse("""{"amountInCents" : 1500, "currency": "AED"}""")
assertNotNull(result.`object`) {
assert(it.amount == AmountInCents(1500))
assert(it.currency == Currency.AED)
}
}
@Test
fun testUnspecifiedCurrency() {
val result = mapper.parse("""{"amountInCents" : "0", "currency": ""}""")
assertNotNull(result.`object`) {
assert(it.amount == AmountInCents.Zero)
assert(it.currency == Currency.Unspecified)
}
}
}
The last 2 tests, where the json key is the alias amountInCents
, are now failing with 1.8.20-Beta vs 1.8.10.