Open
Description
I'm trying to serialize and deserialize an abstract class that has a type parameter, but the deserialization isn't working. Instead of deserializing the JSON into an object of the type parameter's class, Jackson deserializes it into a Map
, so I'm unable to read the object's properties.
Here is the code:
import com.fasterxml.jackson.annotation.{JsonSubTypes, JsonTypeInfo}
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.scala.DefaultScalaModule
object GithubExample {
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "@type")
@JsonSubTypes(Array(
new JsonSubTypes.Type(value = classOf[ResultWrapperSuccess[_]]),
new JsonSubTypes.Type(value = classOf[ResultWrapperFailure[_]])
))
trait ResultWrapperInterface[T] {
protected def obj: T
}
case class ResultWrapperSuccess[T](result: T) extends ResultWrapperInterface[T] {
override protected def obj: T = result
}
case class ResultWrapperFailure[F](failure: F) extends ResultWrapperInterface[F] {
override protected def obj: F = failure
}
case class User(name: String, age: Option[Int])
def main(args: Array[String]): Unit = {
val mapper = new ObjectMapper()
mapper.registerModule(DefaultScalaModule)
val user = User("John Smith", Some(39))
val serializedUser = mapper.writeValueAsString(user)
println(s"(1) serializedUser: $serializedUser")
val deserializedUser = mapper.readValue(serializedUser, classOf[User])
println(s"(2) deserializedUser: $deserializedUser")
println(s"(3) deserializedUser.name: ${deserializedUser.name}")
val wrapperSuccess = ResultWrapperSuccess[User](user)
val serializedSuccess = mapper.writeValueAsString(wrapperSuccess)
println(s"(4) serializedSuccess: $serializedSuccess")
val deserializedSuccess = mapper.readValue(serializedSuccess, classOf[ResultWrapperInterface[User]])
deserializedSuccess match {
case _: ResultWrapperFailure[_] =>
case success: ResultWrapperSuccess[User] =>
println(s"(5) success: $success")
println(s"(6) success.result: ${success.result}")
println(s"(7) success.result.name: ${success.result.name}")
}
}
}
The first part when we serialize and deserialize the User
object works just fine. The code breaks on (7) when it tries to access success.result.name
because success.result
is somehow a Map
instead of a User
.
Here is the output:
(1) serializedUser: {"name":"John Smith","age":39}
(2) deserializedUser: User(John Smith,Some(39))
(3) deserializedUser.name: John Smith
(4) serializedSuccess: {"@type":"GithubExample$ResultWrapperSuccess","result":{"name":"John Smith","age":39}}
(5) success: ResultWrapperSuccess(Map(name -> John Smith, age -> 39))
(6) success.result: Map(name -> John Smith, age -> 39)
Exception in thread "main" java.lang.ClassCastException: scala.collection.immutable.Map$Map2 cannot be cast to GithubExample$User
at GithubExample$.main(GithubExample.scala:55)
at GithubExample.main(GithubExample.scala)
As evidenced by the logs, the serialization seems to be working just fine. Is there something I need to change to get the deserialization working?
Metadata
Metadata
Assignees
Labels
No labels