1

With this jackson-module-scala wrapper

object Json {
  private val ma = new ObjectMapper with ScalaObjectMapper
  ma.registerModule(DefaultScalaModule)
  ma.setSerializationInclusion(Include.NON_NULL)

  def jRead[T: Manifest](value: String): T = ma.readValue[T](value)
  def jWrite(value: Any) = ma.writer.writeValueAsString(value)
  def jNode(value: String) = ma.readTree(value)
}

I try to read subtype (it is just simplified use case without real work):

object TestJTrait extends App {
  trait T1
  object TestJ { def apply[X <: T1: Manifest](s: String): X = jRead[X](s) }
  case class C1(i: Int) extends T1
  TestJ(jWrite(C1(42)))
}

But this attempt results in the error:

Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Can not instantiate abstract type [simple type, class scala.runtime.Nothing$] (need to add/enable type information?)
 at [Source: {"i":42}; line: 1, column: 2]
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148)
    at com.fasterxml.jackson.databind.deser.std.ThrowableDeserializer.deserializeFromObject(ThrowableDeserializer.java:73)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:124)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3051)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2160)
    at com.fasterxml.jackson.module.scala.experimental.ScalaObjectMapper$class.readValue(ScalaObjectMapper.scala:180)

Can anybody, please, suggest a workaround to get the intended behaveur?

Andrew Gaydenko
  • 267
  • 2
  • 11

2 Answers2

1

Since T1 is a trait (abstract type) when deserializing it will try to create an instance of T1 it has no information about C1. You need to hint it.

TestJ[C1](jWrite(C1(42)) should help

Akhil
  • 538
  • 5
  • 13
  • Yes, of course. The aim is `TestJ` knows nothing about `C1`. The wrapper, `T1` and `TestJ` are the only degrees of freedom for instrumentation. – Andrew Gaydenko Aug 20 '14 at 18:22
  • BTW, clumsy workaround is here: https://github.com/FasterXML/jackson-module-scala/issues/155 But it is clumsy :) – Andrew Gaydenko Aug 20 '14 at 18:38
1

If you also have case class C2(i: Int) extends T1, how could it choose between reading C1 or C2? And if you don't, how could it know that you don't? After all, C2 could be anywhere in your program, perhaps in a class which hasn't been loaded yet (and so could C1!). Manifest in [X <: T1: Manifest] won't help either, since the type argument can't be inferred.

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487
  • Yes, it seems it's my fault: I have over-simplified real use case. In fact I need to deserialize `F[X <: T2]` rather `X <: T`. I'll dig in further to try to reduce real use case to something small. – Andrew Gaydenko Aug 20 '14 at 20:42