Raghotham Sripadraj

26 Apr 2015

Parsing JSON in Scala

Introduction

I started a side project on Scala with a group of friends (noobs in scala). We chose Scala because it is well known for type safety and functional programming with support for OOP. One of the important parts of the project was speaking to a REST API which returned JSON responses.

We began our hunt for efficient JSON parsers on scala and soon we were flooded with libraries:

  • spray-json
  • jerkson
  • jackson
  • json4s
  • jacksMapper

With so many options, we were confused! Thanks to this wonderful post from Ooyala Engineering team for putting up a nice comparison of libraries. Finally, we decided to go ahead with json4s because we found it handy to extract objects out of the JSON and also the support it has for Jackson (faster parsing).

Problem

The problem with most of the libraries listed above, especially json4s, is the poor documentation. The examples given are straight forward cases where the structure of the JSON response and the object model are exactly same.

scala> import org.json4s._ 
scala> import org.json4s.jackson.JsonMethods._ 
scala> implicit val formats = DefaultFormats 
// Brings in default date formats etc. 

scala> case class Child(name: String, age: Int, birthdate: Option[java.util.Date]) scala> case class Address(street: String, city: String) 
scala> case class Person(name: String, address: Address, children: List[Child]) 
scala> val json = parse(""" { "name": "joe", "address": { "street": "Bulevard", "city": "Helsinki" }, "children": [ { "name": "Mary", "age": 5, "birthdate": "2004-09-04T18:06:22Z" }, { "name": "Mazy", "age": 3 } ] } """) scala> json.extract[Person] 
res0: Person = Person(joe,Address(Bulevard,Helsinki),List(Child(Mary,5,Some(Sat Sep 04 18:06:22 EEST 2004)), Child(Mazy,3,None)))

What if we want to convert part of the JSON into an object?

From the above example, what if we want to convert only the adress information into an object? There is very little or no documentation which guide beginners to accomplish such task.

img

Link to tweet

Solution

We can traverse the JSON by giving it a path expression. In the above example, we can traverse to the address object by giving it the path from the root, which is “address”

scala> json \ "address"

The above statement will do the traversal and returns a JValue. Once we have the JValue for the address, we can convert it into an Address object by using the extract method

scala> case class Child(name: String, age: Int, birthdate: Option[java.util.Date]) 
scala> case class Address(street: String, city: String) 
scala> val json = parse(""" { "name": "joe", "address": { "street": "Bulevard", "city": "Helsinki" }, "children": [ { "name": "Mary", "age": 5, "birthdate": "2004-09-04T18:06:22Z" }, { "name": "Mazy", "age": 3 } ] } """) 

scala> val addressJson = json \ "address" // Extract address object 
scala> val addressObj = addressJson.extract[Address] 

res1: addressObj: Address = Address(Bulevard,Helsinki)

BOOM! You have extracted an object of type Address from the JSON.

// Extract list of objects 
scala> val children = (json \ "children").extract[List[Child]] 

res2: List[Child] = List(Child(Mary,5,Some(Sat Sep 04 23:36:22 IST 2004)), Child(Mazy,3,None))

Now you have created a List of type Child

The general trend I see is that the Getting started or Usage guides available for various libraries do not help beginners start off quickly on a given problem. We need better beginner docs that showcase examples which are close to real world scenarios.