FasterXML / FasterXML/jackson-module-scala

Cannot deserialize abstract class with type parameter

Đang mở
#435 1 bình luận 0 reaction 0 người được giao Xem trên GitHub
Ngôn ngữ chính
Scala
Star
506
Fork
138
Merge trung bình
3 giờ 6 phút
Pull request đã merge (30 ngày)
48

Mô tả

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?

Hướng dẫn đóng góp

Chưa lập chỉ mục được hướng dẫn đóng góp cho kho mã nguồn này

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.