开发者

How can I use Gson in Scala to serialize a List?

开发者 https://www.devze.com 2023-03-22 07:38 出处:网络
I was hoping to use Scala and Gson together. It seems to mostly work, but when I do something like this, it treats the list as an object, not an array:

I was hoping to use Scala and Gson together. It seems to mostly work, but when I do something like this, it treats the list as an object, not an array:

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

And my JSON turns out something like this:

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

    }
}

Normally Gson converts lists to arrays. I'm sure this is all because Gson doesn't know about Scala's collection classes, but any ideas on what I can do to make this work? Or other suggestions using Scala-native JSON libraries?


You may try lift json, it's native scala lib: http://www.assembla.com/spaces/liftweb/wiki/JSON_Support


Or other suggestions

spray-json is a lightweight, clean and efficient JSON implementation in Scala.

It sports the following features:

  1. Simple immutable model of the JSON language elements
  2. An efficient JSON PEG parser (implemented with parboiled)
  3. Choice of either compact or pretty JSON-to-string printing
  4. Type-class based (de)serialization of custom objects (no reflection, no intrusion)


You can use Java converters in a type adapter, but it's a bit finicky:

  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)


Or other suggestions

The Jackson add-on jackson-module-scala provides some scala support, including serialization of lists.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号