Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

gson

scala

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().toJson(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?

like image 506
Kevin Avatar asked Jul 22 '11 03:07

Kevin


People also ask

How do I use GSON in Scala?

The Steps for Serialization in Scala Using GSONCreate a POJO/case class for the JSON file you wish to read. Now, create a Scala class to parse the JSON and convert it into the scala object (the main magic class). //Serialising the Json String to the Person Object in Scala.

How do you serialize with GSON?

Serialization – Write JSON using Gson Serialization in the context of Gson means converting a Java object to its JSON representation. In order to do the serialization, we need to create the Gson object, which handles the conversion. Next, we need to call the function toJson() and pass the User object. Program output.

Is GSON better than Jackson?

ConclusionBoth Gson and Jackson are good options for serializing/deserializing JSON data, simple to use and well documented. Advantages of Gson: Simplicity of toJson/fromJson in the simple cases. For deserialization, do not need access to the Java entities.

Does GSON serialize static fields?

Gson can serialize static nested classes quite easily.


1 Answers

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)
like image 143
Jenny Avatar answered Sep 18 '22 22:09

Jenny