I followed this guide to use Micronaut Serialization with Jackson annotations.
When I create an abstract Base class and a Derived class, I can use @JsonTypeInfo and @JsonSubTypes to correctly serialize objects of the Derived class.
However, when I serialize an object of OtherClass with a property of type Base but with runtime type Derived, the property is serialized as Base.
The code below should explain my problem. Note that I am using io.micronaut.serde.ObjectMapper, when I replace it with com.fasterxml.jackson.databind.ObjectMapper it works as expected.
Is there a way to make it work using annotations?
import com.fasterxml.jackson.annotation.JsonSubTypes
import com.fasterxml.jackson.annotation.JsonTypeInfo
import io.kotest.core.spec.style.ShouldSpec
import io.kotest.matchers.string.shouldContain
import io.micronaut.serde.ObjectMapper
import io.micronaut.serde.annotation.Serdeable
import io.micronaut.test.extensions.kotest.annotation.MicronautTest
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "class")
@JsonSubTypes(JsonSubTypes.Type(Derived::class))
@Serdeable
abstract class Base(val baseProperty: String = "baseProperty")
@Serdeable
class Derived : Base()
@Serdeable
class OtherClass(val otherProperty: Base)
@MicronautTest
class SerializeTest(objectMapper: ObjectMapper) : ShouldSpec({
should("serialize Derived") {
val derived: Base = Derived()
val valueAsString = objectMapper.writeValueAsString(derived)
/**
* succeeds:
* valueAsString = "{"class":"com.example.Derived","baseProperty":"baseProperty"}"
*/
valueAsString shouldContain "class"
}
should("serialize otherProperty as Derived") {
val derived = Derived()
val otherClass = OtherClass(derived)
val valueAsString = objectMapper.writeValueAsString(otherClass)
/**
* fails:
* valueAsString = "{"otherProperty":{"baseProperty":"baseProperty"}}"
* expected: valueAsString = "{"otherProperty":{"class":"com.example.Derived","baseProperty":"baseProperty"}}"
*/
valueAsString shouldContain "class"
}
})