I am trying to serialise GeneralResponse
:
case class GeneralResponse[T](succeeded: Boolean, payload: Option[T])
and the payload is GroupsForUserResult
:
case class GroupsForUserResult(groups: Seq[UUID]).
I am using mapper.readValue(response.body, classOf[GeneralResponse[GroupsForUserResult]])
but unfortunately the payload is serialised as a Map
and not as the desired case class (GroupForUserResult
).
Because of Java Erasure - Jackson can't know at runtime about the generic type T from the line -
mapper.readValue(response.body, classOf[GeneralResponse[GroupsForUserResult]])
A solution to this problem will be
import com.fasterxml.jackson.core.`type`.TypeReference
mapper.readValue(json, new TypeReference[GeneralResponse[GroupsForUserResult]] {})
This way you provide an instance of TypeReference
with all the needed Type information.
The accepted answer is close enough but you also have to provide the Type Parameter to .readValue
method,
Working example with test,
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"
}
}
The signature of 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));
}
If you don't provide the type parameter, it will blow up with error Customer cannot be cast to scala.runtime.Nothing$