Jackson serialization of polymorphic types without rewriting trait

I am currently working on a research project using Akka Clustering. According to the documentation, Jackson is the preferred serializer, and I am particularly interested in the CBOR binary format due to heavy use of doubles in my work. I am, however, using a heavily polymorphic type pulled in from an external library, and the recommended way to allow for a polymorphic type defined in the Akka docs is to use the @JsonSubTypes and @JsonTypeInfo annotations to define the different types.

Due to large number of extended types from this trait, it would be very difficult to comprehensively define every one of them, and would require editing the source code of the library I’m using. Is there any other way to do so? The code is perfectly serialized and deserialized if sent through the standard Java serialization.

This example is similar to my issue, and is taken from the Akka docs. So my question is essentially: Would it be possible to serialize this case class without the ability to directly add annotations to the trait?

final case class Zoo(primaryAttraction: Animal) extends CborSerializable

sealed trait Animal

final case class Lion(name: String) extends Animal

final case class Elephant(name: String, age: Int) extends Animal
1 Like

I don’t know if it helps for your usage, but it’s possible to define the annotation on the field primaryAttraction instead of the Animal.

  final case class Zoo(
      @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
      @JsonSubTypes(
        Array(
          new JsonSubTypes.Type(value = classOf[Lion], name = "lion"),
          new JsonSubTypes.Type(value = classOf[Elephant], name = "elephant")))
      primaryAttraction: Animal)
      extends TestMessage
  sealed trait Animal
  final case class Lion(name: String) extends Animal
  final case class Elephant(name: String, age: Int) extends Animal
2 Likes

you should be able to do that in code as well.

import com.fasterxml.jackson.module.scala.JacksonModule
import com.fasterxml.jackson.databind.Module.SetupContext
class ZooModule extends JacksonModule {

  override def getModuleName(): String = "zoo"

  this += ((ctx: SetupContext) => {

    ctx.registerSubtypes(classOf[Lion], classOf[Elephant])
  })

}

and then register that in your application.conf

akka.serialization.jackson {
    jackson-modules += "com.acme.ZooModule"
}
2 Likes