在 scala 中使用通用 class 的 Jackson 映射器
Jackson mapper with generic class in scala
我正在尝试连载 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
而不是所需的情况 class (GroupForUserResult
).
由于 Java 擦除 - Jackson 在运行时无法从行 -
中获知通用类型 T
mapper.readValue(response.body, classOf[GeneralResponse[GroupsForUserResult]])
这个问题的解决方案是
import com.fasterxml.jackson.core.`type`.TypeReference
mapper.readValue(json, new TypeReference[GeneralResponse[GroupsForUserResult]] {})
这样您就可以为 TypeReference
的实例提供所有需要的类型信息。
已接受的答案足够接近,但您还必须向 .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$
我正在尝试连载 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
而不是所需的情况 class (GroupForUserResult
).
由于 Java 擦除 - Jackson 在运行时无法从行 -
中获知通用类型 Tmapper.readValue(response.body, classOf[GeneralResponse[GroupsForUserResult]])
这个问题的解决方案是
import com.fasterxml.jackson.core.`type`.TypeReference
mapper.readValue(json, new TypeReference[GeneralResponse[GroupsForUserResult]] {})
这样您就可以为 TypeReference
的实例提供所有需要的类型信息。
已接受的答案足够接近,但您还必须向 .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$