Johan
09/16/2024, 5:24 PMdata class FooDto(
val myId: MyId = MyId(),
@JsonDeserialize(using = SealedTypeDeserializer::class)
val type: SealedType = TypeA.FOO,
)
🧵 for more info
Having just one of them works fine when deserializing, but together does not work. Any clue?Johan
09/16/2024, 5:25 PMfun main() {
val om = ObjectMapper().registerKotlinModule()
val json = om.writeValueAsString(FooDto())
println(json)
val obj = om.readValue<FooDto>(json)
println(obj)
}
data class FooDto(
val myId: MyId = MyId(),
@JsonDeserialize(using = SealedTypeDeserializer::class)
val type: SealedType = TypeA.FOO,
)
@JvmInline
value class MyId(val id: UUID = UUID.randomUUID())
sealed interface SealedType
enum class TypeA: SealedType{
FOO
}
val types: Map<String, SealedType> = listOf(TypeA.entries).flatten().associateBy { it.name }
class SealedTypeDeserializer : JsonDeserializer<SealedType>() {
override fun deserialize(p: JsonParser, ctxt: DeserializationContext): SealedType {
return types[p.text] ?: error("...")
}
}
{"myId":"eedec9c0-2b54-4f58-9f08-5cbba604e51a","type":"FOO"}
Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `SealedType` (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: 55] (through reference chain: no.nav.tilleggsstonader.sak.vilkår.vilkårperiode.FooDto["type"])
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:570)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:440)
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)
Johan
09/16/2024, 6:21 PMObject value = _valueDeserializer.deserialize(p, ctxt);
uses AbstractSerializer when using both fields in the data class.
But when using only type
SealedTypeDeserializer
is used.Johan
09/16/2024, 6:30 PM@JsonDeserialize
to the sealed interface seems to solve the problem.
@JsonDeserialize(using = SealedTypeDeserializer::class)
sealed interface SealedType
But shouldnt it be possible to have it in the DTO-class? On field levelJohan
09/16/2024, 6:37 PMom.registerModule(SimpleModule().also {
it.addDeserializer(SealedType::class.java, SealedTypeDeserializer())
})
Johan
09/16/2024, 6:44 PMwrongwrong
09/18/2024, 2:27 PMJohan
09/18/2024, 6:12 PMwrongwrong
09/19/2024, 9:45 AMJohan
09/19/2024, 2:45 PM