FasterXML / FasterXML/jackson-module-scala

Cannot deserialize abstract class with type parameter

Abierto
#435 1 comentario 0 reacciones 0 asignados Ver en GitHub
Lenguaje dominante
Scala
Estrellas
506
Forks
138
Merge medio
3 h 6 min
PR fusionados (30 d)
48

Descripción

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:
```scala
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:

```scala
(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?

Guía de contribución

No hay ninguna guía de contribución indexada para este repositorio

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.