【问题标题】:How can I use Gson in Scala to serialize a List?如何在 Scala 中使用 Gson 序列化列表?
【发布时间】:2011-07-22 03:52:13
【问题描述】:

我希望同时使用 Scala 和 Gson。它似乎主要工作,但是当我做这样的事情时,它会将列表视为一个对象,而不是一个数组:

case class MyType (val x:String, val y:List[SomeOtherType]) {
    def toJson() = new Gson().toJson(this)
}

我的 JSON 结果是这样的:

{
    "x":"whatever",
    "y": {

    }
}

通常 Gson 将列表转换为数组。我确信这都是因为 Gson 不了解 Scala 的集合类,但是关于我可以做些什么来完成这项工作的任何想法?或者其他使用 Scala 原生 JSON 库的建议?

【问题讨论】:

    标签: scala gson


    【解决方案1】:

    你可以试试lift json,它是原生的scala lib:http://www.assembla.com/spaces/liftweb/wiki/JSON_Support

    【讨论】:

    【解决方案2】:

    你可以使用java转换器:

    import scala.collection.JavaConverters._
    case class MyType (val x:String, val y:List[SomeOtherType]) {
       def toJson() = new Gson().toJson(this.asJava())
    }
    

    【讨论】:

    • 这并不总是适用于像 List[Map[String, Int]] 这样的嵌套类型,它会给出不正确的 json 表示。
    【解决方案3】:

    Or other suggestions

    spray-json 是 Scala 中轻量级、干净且高效的 JSON 实现。

    它具有以下特点:

    1. JSON 语言元素的简单不可变模型
    2. 高效的 JSON PEG 解析器(使用 parboiled 实现)
    3. 选择紧凑或漂亮的 JSON 到字符串打印
    4. 基于类型类的自定义对象(反)序列化(无反射,无入侵)

    【讨论】:

    • spray json 不适用于异构集合,这是一个巨大的限制
    【解决方案4】:

    您可以在类型适配器中使用 Java 转换器,但它有点挑剔:

      case class GsonListAdapter() extends JsonSerializer[List[_]] with JsonDeserializer[List[_]] {
        import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
        import scala.collection.JavaConverters._
    
        @throws(classOf[JsonParseException])
        def deserialize(jsonElement: JsonElement, t: Type, jdc: JsonDeserializationContext): List[_] = {
          val p = scalaListTypeToJava(t.asInstanceOf[ParameterizedType]) // Safe casting because List is a ParameterizedType.
          val javaList: java.util.List[_ <: Any] = jdc.deserialize(jsonElement, p)
          javaList.asScala.toList
        }
    
        override def serialize(obj: List[_], t: Type, jdc: JsonSerializationContext): JsonElement = {
          val p = scalaListTypeToJava(t.asInstanceOf[ParameterizedType]) // Safe casting because List is a ParameterizedType.
          jdc.serialize(obj.asInstanceOf[List[Any]].asJava, p)
        }
    
        private def scalaListTypeToJava(t: ParameterizedType): ParameterizedType = {
          ParameterizedTypeImpl.make(classOf[java.util.List[_]], t.getActualTypeArguments, null)
        }
      }
    
      val gson = new GsonBuilder().registerTypeHierarchyAdapter(classOf[List[_]], new GsonListAdapter()).create()
    
      val l1 = List("a", "c")
      val stringListType = new TypeToken[List[String]] {}.getType
      val json1 = gson.toJson(l1, stringListType)
      println(json1) // ["a","c"]
      val newL1: List[String] = gson.fromJson(json1, stringListType)
      assert(l1 === newL1)
    
      val l2 = List(1, 3)
      val intListType = new TypeToken[List[Int]] {}.getType
      val json2 = gson.toJson(l2, intListType)
      println(json2) // [1,3]
      val newL2: List[Int] = gson.fromJson(json2, intListType)
      assert(l2 === newL2)
    

    【讨论】:

      【解决方案5】:

      或其他建议

      Jackson 附加组件 jackson-module-scala 提供了一些 scala 支持,包括 serialization of lists

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-28
        • 2013-02-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多