Question about serialization with @JsonTypeInfo

It’s actually not a question about Akka, but I really can’t solve it by myself.


  1. I declare a container Tree[T].
trait NodeId {
  def id: Int
}

trait Tree[T <: NodeId] {
  
  def find(id: Int): Option[T]
  
  def size: Int
  
  def root: T
  
  def append(node: T, to: T): Tree[T]
  
  def remove(id: Int): Tree[T]
}

object Tree {
  val RootId : Int = 0
  val EmptyId: Int = -1
  
  def apply[T <: NodeId](root: T): Tree[T] = {
    if (root == null || root.id != RootId)
      throw new IllegalArgumentException("")
    else
      TreeImpl(root :: Nil)
  }
  
  private case class Node(id: Int, child: Int = EmptyId, sibling: Int = EmptyId)
  
  private case class TreeImpl[T <: NodeId](list: List[T], private val tree: List[Node] = Node(RootId) :: Nil)
     extends Tree[T] {
    
    override def find(id: Int): Option[T] = list.find(_.id == id)
    
    def size: Int = list.size
    
    def root: T = this.find(RootId).get
    
    override def append(node: T, to: T): Tree[T] = { ... }

    override def remove(id: Int): Tree[T] = { ... }      
  }
}
  1. I delcare a drived class.
case class Stage(id: Int, title: String) extends NodeId

object Stage {
  val Root: Stage = Stage(id = RootId, title = "ROOT")
}
  1. I use Tree[Stage] to store the state of entity.
trait Plan extends Aggregate {
  type State = Plan
  
  def projectId: String
  
  def stages: Tree[Stage]
}

final case class PlacedPlan(id: String, projectId: String, stages: Tree[Stage] = Tree[Stage](Root)) extends Plan { ... }

Now, I get the error message: State [PlacedPlan(...,TreeImpl(List(...),List(...))] isn't serializable.

I think it should put @JsonTypeInfo to somewhere of Tree[T], TreeImpl or trait Plan. I read the reference of @JsonTypeInfo. But Tree isn’t a collection like List or Array, even @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) or @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type") @JsonSubTypes(Array(new JsonSubTypes.Type(value = classOf[Tree[_]], name = "tree"))) not going,

I don’t know how to do, give me some help…

Thanks.

I think the key is serializer doesn’t know what the Tree[T] is.

  1. The Json result what I want is:
{
    "title": "Project",
    "description": "A project",
    "type": "object",
    "properties": {
        "projectId": {
            "description": "The unique identifier for a project",
            "type": "string"
        },
        "Stages": {
            "description": "Stages of the project.",
            "type":"object",
            "properties":{
                "stage": {
                "type": "array",
                "items": {
                    "type": "object",
                    "properties" :{
                        "id": {
                            "type":"integer"
                        },
                        "title":{
                            "type":"string"
                        }
                      }
                  }
                },
                "nodes":{
                    "type": "array",
                    "items": {
                        "type": "object",
                        "properties" :{
                            "id": {
                                "type":"integer"
                            },
                            "child":{
                                "type":"integer"
                            },
                            "sibling":{
                                "type":"integer"
                            }
                      }
                  }
                }
              }
          }
     }
}
  1. the inheritance hierarchy shoud be this:
case class Project (
  projectId: String,
  Stages: Stages
)

case class Stages (
  stage: List[Stage],
  nodes: List[Nodes]
)

case class Stage (
    id: Int,
    title: String
)

case class Nodes (
  id: Int,
  child: Int,
  sibling: Int
)
  1. So the serializer should translate Tree[Stage] to Stages, but it doesn’t know how to do.

It doesn’t help with a combination of @JsonTypeInfo and @JsonSubTypes like described in the Akka docs about polymorphic types here? Serialization with Jackson • Akka Documentation

Thank you. I read it and find that customize serializer and deserializer is only way.

I’m wondering how to adapt the generic type param T in serializer but not Stage only. I want to keep the abstract of Tree.

But now, I have to implement a Stages without generic abstract which can be serialized in my project. the Stage must keep the info of tree node(child/sibling) by itself.

case class Stage(id         : Int,
                 child      : Int ,
                 sibling    : Int,
                 title      : String,
                )

final case class Stages(private val list: List[Stage]) {...}