You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I searched in the issues and found nothing similar.
I searched in the issues of databind and other modules used and found nothing similar.
I have confirmed that the problem only occurs when using Kotlin.
Describe the bug
When using kotlin, the @JsonTypeInfo(use = CLASS) does nothing if another field is a value class.
To Reproduce
packageapp.interceptor.core.filterimportcom.fasterxml.jackson.annotation.JsonTypeInfoimportcom.fasterxml.jackson.annotation.JsonTypeInfo.Id.CLASSimportcom.fasterxml.jackson.databind.ObjectMapperimportcom.fasterxml.jackson.databind.SerializationFeatureimportcom.fasterxml.jackson.datatype.jsr310.JavaTimeModuleimportcom.fasterxml.jackson.module.kotlin.KotlinFeatureimportcom.fasterxml.jackson.module.kotlin.kotlinModuleimportcom.fasterxml.jackson.module.kotlin.readValueimportkotlinx.coroutines.delayimportkotlin.time.Durationimportkotlin.time.Duration.Companion.secondsval mapper:ObjectMapper=ObjectMapper()
.registerModule(kotlinModule {
enable(KotlinFeature.UseJavaDurationConversion)
})
.registerModule(JavaTimeModule())
.disable(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS)
interfaceFilter {
suspendfunaccept(): Boolean
}
data objectAlwaysTrueFilter : Filter {
overridesuspendfunaccept() =true
}
data classAllFilter(@JsonTypeInfo(use =CLASS) valfilters:List<Filter>) : Filter {
constructor(vararg filters:Filter) :this(filters.asList())
overridesuspendfunaccept() = filters.all { it.accept() }
}
data classTimeoutFilter(valtimeout:Duration, @JsonTypeInfo(use =CLASS) valfilter:Filter) : Filter {
overridesuspendfunaccept(): Boolean {
TODO("Not yet implemented")
}
}
data classDelayFilter(valduration:Duration) : Filter {
overridesuspendfunaccept(): Boolean {
delay(duration)
returntrue
}
}
funmain() {
val allFilter =AllFilter(AlwaysTrueFilter)
val jsonAllFilter = mapper.writeValueAsString(allFilter)
println(jsonAllFilter)
println(mapper.readValue<AllFilter>(jsonAllFilter))
val delayFilter =DelayFilter(1.seconds)
val jsonDelayFilter = mapper.writeValueAsString(delayFilter)
println(jsonDelayFilter)
println(mapper.readValue<DelayFilter>(jsonDelayFilter))
val timeoutFilter =TimeoutFilter(1.seconds, AlwaysTrueFilter)
val jsonTimeoutFilter = mapper.writeValueAsString(timeoutFilter)
println(jsonTimeoutFilter)
println(mapper.readValue<TimeoutFilter>(jsonTimeoutFilter))
}
This produces:
{"filters":[{"@class":"app.interceptor.core.filter.AlwaysTrueFilter"}]}
AllFilter(filters=[AlwaysTrueFilter])
{"duration":"PT1S"}
DelayFilter(duration=1s)
{"timeout":"PT1S","filter":{}}
Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `app.interceptor.core.filter.Filter` (no Creators, like default constructor, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 28] (through reference chain: app.interceptor.core.filter.TimeoutFilter["filter"])
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1887)
at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:414)
at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1375)
at com.fasterxml.jackson.databind.deser.AbstractDeserializer.deserialize(AbstractDeserializer.java:274)
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:545)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeWithErrorWrapping(BeanDeserializer.java:576)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:446)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1493)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:348)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:185)
at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:342)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4905)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3848)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3831)
at app.interceptor.core.filter.TestKt.main(Test.kt:59)
at app.interceptor.core.filter.TestKt.main(Test.kt)
Expected behavior
Everything works correctly if @JsonTypeInfo(use = CLASS) is used by itself (AllFilter) or a value class field is used by itself (DelayFilter).
I would expect that this will work when I use both a value class field and a JsonTypeInfo field (TimeoutFilter), but it breaks.
Search before asking
Describe the bug
When using kotlin, the
@JsonTypeInfo(use = CLASS)
does nothing if another field is a value class.To Reproduce
This produces:
Expected behavior
Everything works correctly if
@JsonTypeInfo(use = CLASS)
is used by itself (AllFilter
) or a value class field is used by itself (DelayFilter
).I would expect that this will work when I use both a value class field and a
JsonTypeInfo
field (TimeoutFilter
), but it breaks.Versions
Kotlin: 2.0.20
Jackson-module-kotlin: 2.17.2
Jackson-databind: 2.17.2
Additional context
No response
The text was updated successfully, but these errors were encountered: