IT, Simplicity

Play! Scala and JSON

Update: If you need to have custom de/serialization of some types, check out this new post

I’ve been working with Play! Scala for a couple of months now, and the experience is really good – the combination of the Scala language and the sound design principles of Play! make web-development a real pleasure.

One of the aspects I have been fighting with for a while (and which had initially put me off writing my first bigger Play! application with Play! Scala) is the lack of simple support for JSON de/serialization. With simple I mean the possibility to turn a case class into a JSON string and back, and to additionally have access to a couple of more advanced features that are often required (e.g. implementing custom serialization of specific types).

From the recent development on the Play! Scala Github repository, it looks as tough sjson will be used as the integrated library with the framework.

I have tried out sjson and my experience with it wasn’t all that good, I outlined the issues I had with it (mainly that it doesn’t offer support for custom de/serialization of Java beans) in this post to the Play! mailing-list.

The alternative I found bears the sexy name of Jerkson and is developed by Coda Hale. It is a scala wrapper for Jackson which supports all kind of features you may want from a JSON library.

The latest release now makes the integration of Jerkson very easy, as it addresses two issues that happened in the Play! context: it finds the custom classloader Play! uses, and allows to deserialize case classes with more than one constructor (this can be problematic in some cases, and Play! adds an empty constructor to case classes, necessary for e.g. the integration with SnakeYML).

Since the releases are available via Maven, it is possible to easily get Jerkson into a Play! Scala project by adding the following dependency to dependencies.yml:

- com.codahale -> jerkson_2.8.1 0.4.2-SNAPSHOT:
    exclude:
        - org.scala-lang -> scala-library
repositories:
    - codahale:
        type: iBiblio
        root: "http://repo.codahale.com/"
        contains:
            - com.codahale.*

And… that’s it. You can now use Jerkson like this (don’t forget to run a play dependencies):

import com.codahale.jerkson.Json._
case class Foo(bar: String, baz: Int)
val serialized: String = generate(Foo("bar", 42))
val deserialized: Foo = parse[Foo](serialized)

Additionally, you can use a trait to mixin with your controllers in order to make JSON serialization look more integrated with other actions:

trait JsonAction { self: Controller =>
  def Json(data: AnyRef): Result = new Result() {
    def apply(request: Request, response: Response) {
      val encoding = getEncoding
      setContentTypeIfNotSet(response, "application/json; charset=" + encoding)
      response.out.write(Json.generate(data).getBytes(encoding))
    }
  }
}
Standard