JSON Support

JSON is a lightweight, text-based, language-independent data interchange format described at json.org; for more involved description please take a look of RFC 4627.

Why would I need JSON?

JSON’s small and simple representation is suitable for storing and transmitting structured data . JSON is most commonly used to transfer data from a web service to a browser-based JavaScript application.

As one of the JSON’s design goals was to be a subset of JavaScript it is also really handy way to manipulate all kinds of data in Javascript-heavy application.

JSON is a subset of javascript as JSON is derived from the object literals of JavaScript; it can represent four primitive types and two structured types ; “object” and “array” are based on the conventions of JavaScript.

lift-json library

In Lift, parsing and formatting utilities for JSON are provided by lift-json library.

A central concept in lift-json library is JSON AST which models the structure of a JSON document as a syntax tree; all features are implemented in terms of AST. It provides a case class for each of the above mentioned JSON primitive and structured type, and provides functions used to transform the AST itself, or to transform the AST between different formats.

Following graph summarizes common transformations:

Further introduction and detailed examples: Please refer to the lift-json readme file

Tips

Case Classes

lift-json can serialize case classes and can extract them from JSON strings. For example:

scala> import net.liftweb.json._
scala> import net.liftweb.json.JsonParser._
scala> implicit val formats = DefaultFormats // Brings in default date formats etc.
scala> case class Child
scala> case class Address
scala> case class Person
scala> val json = parse

scala> json.extract[Person] 
res0: Person = Person(joe,Address,List(Child(Mary,5,Some), Child))

Note: If you are trying this in the Scala REPL it will fail. Unfortunately case classes must be defined outside the REPL session in order for extraction to succeed.

Prior to Lift 2.3, if you had a list of people as your root JSON object you would need to manually extract each person:

scala> val json = parse
scala> val people: List[Person] = json.children.map

Optional Parameters

You can wrap your case class parameters in Options and then their presence won’t be required in the JSON string being parsed:

scala> case class Person
scala> val json = parse
scala> json.extract[Person]
res0: Person = Person(joe,None,List())

You’ll notice that Lists can also be empty. The same is true for Arrays and Sets but not for Maps.

Empty collection parameters will be included when a case class instance is serialized but not Option-al ones:

import net.liftweb.json.Serialization.write
scala> case class Person
scala> val joe = Person
scala> write
res0: String = {"name":"Joe","children":[]}