Hi,

I am using *"com.fasterxml.jackson.module" %% "jackson-module-scala" % 
"2.10.0"*

I am using a deserializer to read json message post into kafka.
At a time we faced a *java.lang.ClassCastException: java.lang.Integer 
cannot be cast to java.lang.Long*.
I dig into this issue and found the related issues in github and the FAQ 
https://github.com/FasterXML/jackson-module-scala/wiki/FAQ that indicate to 
annotate offending field with *@JsonDeserialize*.
I tried this with no success.
My case class look like this (adapt like the one in the test case 
https://github.com/FasterXML/jackson-module-scala/blob/master/src/test/scala/com/fasterxml/jackson/module/scala/deser/PrimitiveContainerTest.scala
)
case class AnnotatedOptionLongWithDash(@JsonDeserialize(contentAs = classOf[
java.lang.Long]) `value-long`: Option[Long])

I try to understand why the test in scala module works but not our code and 
found that this is because the property contain a dash and we kept the dash 
in the scala props (Disgusting!).
I finally try to add @JsonProperty annotation to remove the dash and it's 
working.

I am not sure this issue is related to jackson deserialization and can be 
fix or it's scala/java that do something when a property have a dash in it.
At least it can help to add a note about this in the workarounds of the FAQ.

Here some tests case to reproduce the issue.

import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import com.fasterxml.jackson.module.scala.{DefaultScalaModule, 
ScalaObjectMapper}
import org.scalatest.{Matchers, WordSpec}

case class AnnotatedOptionLong(@JsonDeserialize(contentAs = 
classOf[java.lang.Long]) valueLong: Option[Long])

case class AnnotatedOptionLongWithDash(@JsonDeserialize(contentAs = 
classOf[java.lang.Long]) `value-long`: Option[Long])

case class 
AnnotatedOptionLongWithDashButChangeToCamelCase(@JsonProperty("value-long") 
@JsonDeserialize(contentAs = classOf[java.lang.Long]) valueLong: Option[Long])

class JacksonSerializationIssueTest extends WordSpec with Matchers {

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

  def deserialize[T](data: Array[Byte])(implicit m: Manifest[T]): T = {
    try {
      objectMapper.readValue(data)
    } catch {
      case e: Throwable =>
        throw new RuntimeException("Error deserializing JSON message", e)
    }
  }

  def serialize[T](data: T): Array[Byte] = {
    try {
      objectMapper.writeValueAsBytes(data)
    } catch {
      case e: Throwable =>
        throw new RuntimeException("Error serializing JSON message", e)
    }
  }

  def useOptionLong(v: Option[Long]): Long = v.map(_ * 2).getOrElse(0)

  "same as in test source of jackon library" in {
    // check deserialization
    val v1 = deserialize[AnnotatedOptionLong]("""{"valueLong":151}""".getBytes)
    v1 shouldBe AnnotatedOptionLong(Some(151L))
    v1.valueLong.get shouldBe 151L

    // serialize from case class then deserialize and then apply the method 
that will fail
    val v2 = 
JacksonMapper.deserialize[AnnotatedOptionLong](JacksonMapper.serialize(AnnotatedOptionLong(Some(152))))
    v2 shouldBe AnnotatedOptionLong(Some(152L))
    v2.valueLong.get shouldBe 152L
    useOptionLong(v2.valueLong) shouldBe 304
  }

  "failing test because of backtick prop name either if we apply the annotation 
@JsonDeserialize(contentAs = classOf[java.lang.Long]) " in {
    // check deserialization
    val v1 = 
deserialize[AnnotatedOptionLongWithDash]("""{"value-long":251}""".getBytes)
    v1 shouldBe AnnotatedOptionLongWithDash(Some(251L))
    v1.`value-long`.get shouldBe 251L

    // serialize from case class then deserialize and then apply the method 
that will fail
    val v2 = 
JacksonMapper.deserialize[AnnotatedOptionLongWithDash](JacksonMapper.serialize(AnnotatedOptionLongWithDash(Some(252))))
    v2 shouldBe AnnotatedOptionLongWithDash(Some(252L))
    v2.`value-long`.get shouldBe 252L
    useOptionLong(v2.`value-long`) shouldBe 504
  }

  "working solution because we rename the prop with a dash to a camel case 
prop" in {
    // check deserialization
    val v1 = 
deserialize[AnnotatedOptionLongWithDashButChangeToCamelCase]("""{"value-long":351}""".getBytes)
    v1 shouldBe AnnotatedOptionLongWithDashButChangeToCamelCase(Some(351L))
    v1.valueLong.get shouldBe 351L

    // serialize from case class then deserialize and then apply the method 
that will fail
    val v2 = 
JacksonMapper.deserialize[AnnotatedOptionLongWithDashButChangeToCamelCase](JacksonMapper.serialize(AnnotatedOptionLongWithDashButChangeToCamelCase(Some(352))))
    v2 shouldBe AnnotatedOptionLongWithDashButChangeToCamelCase(Some(352L))
    v2.valueLong.get shouldBe 352L
    useOptionLong(v2.valueLong) shouldBe 704
  }

}



-- 
You received this message because you are subscribed to the Google Groups 
"jackson-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to jackson-user+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/jackson-user/cb00a30a-53a3-4ee1-b047-fcf5f25f7461%40googlegroups.com.

Reply via email to