杰克逊映射器与scala中的通用类

时间:2015-04-22 19:01:42

标签: json scala serialization jackson case-class

我正在尝试序列化GeneralResponse

case class GeneralResponse[T](succeeded: Boolean, payload: Option[T])

,有效负载为GroupsForUserResult

case class GroupsForUserResult(groups: Seq[UUID]).

我正在使用mapper.readValue(response.body, classOf[GeneralResponse[GroupsForUserResult]]),但不幸的是,有效负载被序​​列化为Map而不是所需的案例类(GroupForUserResult)。

2 个答案:

答案 0 :(得分:6)

由于Java Erasure - 杰克逊在运行时无法从线路上了解泛型类型T -

mapper.readValue(response.body, classOf[GeneralResponse[GroupsForUserResult]])

此问题的解决方案将是

import com.fasterxml.jackson.core.`type`.TypeReference

mapper.readValue(json, new TypeReference[GeneralResponse[GroupsForUserResult]] {})

这样您就可以提供TypeReference的实例以及所有需要的类型信息。

答案 1 :(得分:1)

接受的答案足够接近,但您还必须将类型参数提供给.readValue方法,

带测试的工作示例

import com.fasterxml.jackson.core.`type`.TypeReference
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import org.scalatest.{FunSuite, Matchers}

case class Customer[T](name: String, address: String, metadata: T)

case class Privileged(desc: String)

class ObjectMapperSpecs extends FunSuite with Matchers {

  test("deserialises to case class") {

    val objectMapper = new ObjectMapper()
      .registerModule(DefaultScalaModule)

    val value1 = new TypeReference[Customer[Privileged]] {}

    val response = objectMapper.readValue[Customer[Privileged]](
      """{
           "name": "prayagupd",
           "address": "myaddress",
           "metadata": { "desc" : "some description" }
         }
      """.stripMargin, new TypeReference[Customer[Privileged]] {})

    response.metadata.getClass shouldBe classOf[Privileged]
    response.metadata.desc shouldBe "some description"
  }

}

com.fasterxml.jackson.databind.ObjectMapper#readValue的签名,

public <T> T readValue(String content, TypeReference valueTypeRef)
    throws IOException, JsonParseException, JsonMappingException
{
    return (T) _readMapAndClose(_jsonFactory.createParser(content), _typeFactory.constructType(valueTypeRef));
} 

如果您未提供类型参数,则会出现错误Customer cannot be cast to scala.runtime.Nothing$