2013-10-15 47 views
6

我們都知道泛型類型在Java和Scala下受到類型擦除。但是我們在斯卡拉使用傑克遜和斯卡拉傑克遜模塊遇到了一個奇怪的問題。奇怪的使用Scala和Jackson和java.lang.Integer或Scala的泛型類型的反序列化問題.Int

我創建了一個小測試來顯示問題。

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's 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) 
    } 
} 

上面的輸出是:

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

從何與此不同的這種行爲? Generic Type Erasure,傑克遜傑克遜Scala模塊?

+0

我對Scala並不熟悉,但我的猜測是,傑克遜有一個內置的轉換器,知道如何處理Java類型轉換,但不是Scala轉換。 – chrylis

+0

嗯,也許......創建了一個問題,交叉引用這個問題:https://github.com/FasterXML/jackson-module-scala/issues/104 – longliveenduro

回答

3

這已成爲我寫了這樣一個共同的問題的情況下FAQ

[A]原始類型參數表示爲JVM的Object。 Scala模塊已通知Jackson,Option實際上是一種容器類型,但它依靠Java反射來確定包含的類型,並且提出Object

此用例的當前解決方法是將@JsonDeserialize註釋添加到目標成員。具體地,該註釋具有一組參數,這些參數可以被用於不同的情況:

  • contentAs爲集合或圖值(負載)
  • keyAs爲地圖鍵(目前不支持)

實例如何使用這個註釋can be found in the tests directory

在好奇的FAQ中有很多更多的細節。

+0

感謝您的好解釋和FAQ項目! – longliveenduro

0

這似乎是因爲java.lang.Integerconstructor這需要一個字符串,它允許解串器使用,對於Integer,而不是與Int

+0

不,如果你在調試器中運行程序並設置使用int和String的java.lang.Integer構造函數中的斷點沒有String構造函數的命中,只存在於int類型的構造函數中! – longliveenduro