Strange deserialization problems with typical types using Scala and Jackson and java.lang.Integer or scala.Int

We all know that generic types are subject to type erasure in Java and Scala. But we ran into a strange problem in Scala using Jackson and the Scala Jackson module.

I created a little test to show the problem.

import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.module.scala.DefaultScalaModule object GenericTest { case class TestWithInt(id: Option[Int]) case class TestWithInteger(id: Option[Integer]) def main(args: Array[String]) { val mapper = new ObjectMapper() mapper.registerModule(DefaultScalaModule) // Test with scala Int val test = mapper.readValue[TestWithInt]("""{ "id" : 5 }""", classOf[TestWithInt]) print("Test 1: ") println(test.id.get + 1) val test2 = mapper.readValue[TestWithInt]("""{ "id" : "5" }""", classOf[TestWithInt]) print("Test 2: ") try { println(test2.id.get + 1) } catch { case e: ClassCastException => println(e.getMessage) } // Test with java.lang.Integer val test3 = mapper.readValue[TestWithInteger]("""{ "id" : 5 }""", classOf[TestWithInteger]) print("Test 3: ") println(test3.id.get + 1) val test4 = mapper.readValue[TestWithInteger]("""{ "id" : "5" }""", classOf[TestWithInteger]) print("Test 4: ") println(test4.id.get + 1) } } 

The conclusion above:

 Test 1: 6 Test 2: java.lang.String cannot be cast to java.lang.Integer Test 3: 6 Test 4: 6 

Where does this other behavior come from? Generic Type Erasure, Jackson, Jackson Scala Module?

+6
source share
2 answers

This becomes such a common question that I wrote a FAQ for it:

[A] l1 parameters of a primitive type are represented as Object for the JVM .... The Scala module told Jackson that Option is really a container type, but it relies on Java reflection to determine what type it contains and has Object .

The current workaround for this use case is to add the @JsonDeserialize annotation to the target member. In particular, this annotation contains a set of parameters that can be used for different situations:

  • contentAs for collections or map values ​​(supported)
  • keyAs for Map keys (not currently supported)

Examples of using this annotation can be found in the test catalog .

The FAQ is often asked more detailed questions for the curious.

+3
source

Source: https://habr.com/ru/post/955976/


All Articles