原始类型的Scala集合的Gson反序列化

时间:2018-08-15 16:27:11

标签: json scala gson deserialization

我正在尝试使用gson反序列化Scala案例类,并且当案例类包含原始类型的集合时遇到问题。

考虑以下代码:

准备gson:

import com.google.gson._
import scala.collection.JavaConverters._

//custom deserialization for Seq
class SeqDeserializer[T] extends JsonDeserializer[scala.collection.Seq[T]] {

  override def deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): scala.collection.Seq[T] = {

    //this is the `Type` of `T`
    val innerType = typeOfT.asInstanceOf[ParameterizedType].getActualTypeArguments.head //there is only one type arg since it a Seq
    println(s"json=$json, type=$innerType")
    json
      .getAsJsonArray
      .asScala
      .map(j => context.deserialize[T](j, innerType))
      .toSeq
  }
}

//initiate gson:
val builder = new GsonBuilder().registerTypeAdapter(classOf[scala.collection.Seq[Any]], new SeqDeserializer[Any])
val gson = builder.create()

要反序列化的类:

case class Top(
              ints: Seq[Int] = Nil,
              items: Seq[Item] = Nil
              )

case class Item(i: Int = 0)

重新产生问题的代码:

val json =
  """
    |{
    |   "ints": [1,2,3],
    |   "items": [
    |   {
    |      "i": 1
    |   },
    |   {
    |      "i": 2
    |   }
    |   ]
    |}
  """.stripMargin

val res = gson.fromJson(json, classOf[Top])

println(res) //1
println(res.items.map(_.toString)) //2
println(res.ints.map(_.toString))  //3

第一个println将打印:

  

顶部(列表(1.0,2.0,3.0),列表(项目(1),项目(2)))

我们已经看到存在问题,因为ints中的值是doubles
第二个println将打印:

  

列表(Item(1),Item(2))

(符合预期)
在第三个println上,我遇到了一个例外:

  

java.lang.Double无法转换为java.lang.Integer   java.lang.ClassCastException:无法将java.lang.Double强制转换为   java.lang.Integer在   scala.runtime.BoxesRunTime.unboxToInt(BoxesRunTime.java:101)

SeqDeserializer内的印刷品中

我们得到:

  

json = [1,2,3],类型= class java.lang.Object
  json = [{“ i”:1},{“ i”:2}],type = class Item

我们可以看到,对于Seq[Item]gson正确地将内部类型标识为Item
但对于Seq[Int],内部类型标识为Object,然后解析为Double而不是Int
我猜想这与Int

的拳击有关

如何使gson在集合内的原始类型上正常工作?

0 个答案:

没有答案