Невозможно десериализовать абстрактный класс с параметром типа с помощью модуля Jackson Scala. - PullRequest
2 голосов
/ 19 сентября 2019

Я использую Модуль Джексона Scala , чтобы попытаться сериализовать и десериализовать классы случаев Scala как JSON.

В частности, я пытаюсь сделать это с абстрактным классом, который имеетпараметр типа, но десериализация не работает.Вместо десериализации JSON в объект класса параметра типа Джексон десериализует его в Map, поэтому я не могу прочитать свойства объекта.

Вот код:

import com.fasterxml.jackson.annotation.{JsonSubTypes, JsonTypeInfo}
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.scala.DefaultScalaModule

object StackOverflowExample {

  @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}")
    }

  }

}

Первая часть, когда мы сериализуем и десериализуем объект User, работает просто отлично.Код прерывается на (7), когда он пытается получить доступ к success.result.name, потому что success.result является каким-то образом Map вместо User.

Вот вывод:

(1)        serializedUser: {"name":"John Smith","age":39}
(2)      deserializedUser: User(John Smith,Some(39))
(3) deserializedUser.name: John Smith
(4)     serializedSuccess: {"@type":"StackOverflowExample$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 StackOverflowExample$User
    at StackOverflowExample$.main(StackOverflowExample.scala:55)
    at StackOverflowExample.main(StackOverflowExample.scala)

Как видно из логов, сериализация, кажется, работает просто отлично.Что-то, что мне нужно изменить, чтобы заставить работать десериализацию?

...