Scala 2.10 + Json serialization and deserialization Scala 2.10 + Json serialization and deserialization json json

Scala 2.10 + Json serialization and deserialization


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.ObjectMapperimport com.fasterxml.jackson.module.scala.DefaultScalaModuleimport 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.


Mentioning json4s that wraps jackson, lift-json or its own native implementation as a long term solution:


I can heartily recommend argonaut for json support in scala. All you need to configure it to serialize your Customer object is one line:

implicit lazy val CodecCustomer: CodecJson[Customer] =casecodec6(Customer.apply, Customer.unapply)("id","name","address","city","state","user_id")

That will pimp your class to give it an .asJson method which turns it into a string. It will also pimp the string class to give it a method .decodeOption[List[Customer]] to parse strings. It handles the options in your class fine. Here is a working class with a passing test and a running main method which you can drop into a git clone of argonaut to see it all working fine:

package argonaut.exampleimport org.specs2.{ScalaCheck, Specification}import argonaut.CodecJsonimport argonaut.Argonaut._case class Customer(id: Int, name: String, address: Option[String],                    city: Option[String], state: Option[String], user_id: Int)class CustomerExample extends Specification with ScalaCheck {  import CustomerExample.CodecCustomer  import CustomerExample.customers  def is = "Stackoverflow question 12591457 example" ^    "round trip customers to and from json strings " ! {      customers.asJson.as[List[Customer]].toOption must beSome(customers)    }}object CustomerExample {  implicit lazy val CodecCustomer: CodecJson[Customer] =    casecodec6(Customer.apply, Customer.unapply)("id","name","address","city","state","user_id")  val customers = List(    Customer(1,"one",Some("one street"),Some("one city"),Some("one state"),1)    , Customer(2,"two",None,Some("two city"),Some("two state"),2)    , Customer(3,"three",Some("three address"),None,Some("three state"),3)    , Customer(4,"four",Some("four address"),Some("four city"),None,4)  )  def main(args: Array[String]): Unit = {    println(s"Customers converted into json string:\n ${customers.asJson}")    val jsonString =      """[        |   {"city":"one city","name":"one","state":"one state","user_id":1,"id":1,"address":"one street"}        |   ,{"city":"two city","name":"two","state":"two state","user_id":2,"id":2}        |   ,{"name":"three","state":"three state","user_id":3,"id":3,"address":"three address"}        |   ,{"city":"four city","name":"four","user_id":4,"id":4,"address":"four address"}        |]""".stripMargin    var parsed: Option[List[Customer]] = jsonString.decodeOption[List[Customer]]    println(s"Json string turned back into customers:\n ${parsed.get}")  }}

The developers are also helpful and responsive to folks getting started.