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