Scala 2.10 + Json serialization and deserialization

user1698607 picture user1698607 · Sep 25, 2012 · Viewed 39.3k times · Source

Scala 2.10 seems to have broken some of the old libraries (at least for the time being) like Jerkson and lift-json.

The target usability is as follows:

case class Person(name: String, height: String, attributes: Map[String, String], friends: List[String])

//to serialize
val person = Person("Name", ....)
val json = serialize(person)

//to deserialize
val sameperson = deserialize[Person](json)

But I'm having trouble finding good existing ways of generating and deserializing Json that work with Scala 2.10.

Are there best practice ways of doing this in Scala 2.10?

Answer

Kipton Barros picture Kipton Barros · Jan 5, 2013

Jackson is a Java library to process JSON fast. The Jerkson project wraps Jackson, but appears to be abandoned. I've switched to Jackson's Scala Module for serialization and deserialization to native Scala data structures.

To get it, include the following in your build.sbt:

libraryDependencies ++= Seq(
  "com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.1.3",
   ...
)

Then your examples will work verbatim with the following Jackson wrapper (I extracted it from jackson-module-scala test files):

import java.lang.reflect.{Type, ParameterizedType}
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.`type`.TypeReference;

object JacksonWrapper {
  val mapper = new ObjectMapper()
  mapper.registerModule(DefaultScalaModule)
  
  def serialize(value: Any): String = {
    import java.io.StringWriter
    val writer = new StringWriter()
    mapper.writeValue(writer, value)
    writer.toString
  }

  def deserialize[T: Manifest](value: String) : T =
    mapper.readValue(value, typeReference[T])

  private [this] def typeReference[T: Manifest] = new TypeReference[T] {
    override def getType = typeFromManifest(manifest[T])
  }

  private [this] def typeFromManifest(m: Manifest[_]): Type = {
    if (m.typeArguments.isEmpty) { m.runtimeClass }
    else new ParameterizedType {
      def getRawType = m.runtimeClass
      def getActualTypeArguments = m.typeArguments.map(typeFromManifest).toArray
      def getOwnerType = null
    }
  }
}

Other Scala 2.10 JSON options include Twitter's scala-json based on the Programming Scala book--it's simple, at the cost of performance. There is also spray-json, which uses parboiled for parsing. Finally, Play's JSON handling looks nice, but it does not easily decouple from the Play project.