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:

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.
tweet
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.

scala> val children = (json \ "children").extract[List[Child]]  // Extract list of objects
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.

 
5
Kudos
 
5
Kudos

Now read this

DLNA on Raspberry Pi

I always wanted to setup a media server at home for the following reasons: Reduce redundancy - having multiple copies of media for different devices like phone, tablet, smart TV etc Ease of use - no need to copy files to and from devices... Continue →