Skip to content

nbenns/ScalaTalkJsonWrite

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ScalaTalkJsonWrite

This project was created for a Scala Toronto Talk.
Slides are located here

The idea in this talk is to implement a JSON serializer library that we can use with the least amount of effort possible, and the least amount of bleed into our business design.

It starts with a standard OOP design pattern and then uses some of Scala's functional design patterns to implement more levels of abstraction.

Example 1 - Initial OOP Design

This branch is the initial OOP design.

Library Design

The JSON language is made up of some specific objects:

  • Boolean
  • Number
  • String
  • Array
  • Object

Each Noun in our language can be "stringified", meaning it can be converted to a String which can be easily sent across the network.

We start with defining an abstract class to represent the language, with our stringify method to convert each of our Nouns into their String representation.

abstract class Json {
  def stringify: String
}

Then each of the Nouns within the JSON language are implemented as classes and inherit from our language base.

Boolean

class JsonBoolean(b: Boolean) extends Json {
  override def stringify = b.toString
}

Number

class JsonNumber(n: Double) extends Json {
  override def stringify =
    if (n % 1 == 0) n.toInt.toString
    else n.toString
}

String

class JsonString(s: String) extends Json {
  override def stringify = "\"" + s + "\""
}

Array

class JsonArray(elements: Json*) extends Json {
  override def stringify = "[" + elements.map(_.stringify).mkString(", ") + "]"
}

Object

class JsonObject(pairs: (String, Json)*) extends Json {
  private val stringifyPair = ((k: String, v: Json) => {
    val key = new JsonString(k).stringify
    val value = v.stringify

    s"$key: $value"
  }).tupled

  override def stringify = "{" + pairs.map(stringifyPair).mkString(", ") + "}"
}

Business Model

The business model of the application is a Family. A Family has a Name, a mother, a father, and children.

Each family member is represented as a Person, and a Person has a Name, an Age and is either Alive or Dead


Person

class Person(name: String, age: Int, alive: Boolean, nickName: Option[String])

Family

class Family(surName: String, mother: Person, father: Person, children: List[Person])

Bringing it together

We want to represent our Business Model as JSON so we can send it across the internet. To do this we extend our models from JSON and implement the stringify method.

Person

class Person(name: String, age: Int, alive: Boolean, nickName: Option[String]) extends Json {
  override def stringify =
    if (nickName.isEmpty) new JsonObject(
      "name" -> new JsonString(name),
      "age" -> new JsonNumber(age),
      "alive" -> new JsonBoolean(alive)
    ).stringify else new JsonObject(
      "name" -> new JsonString(name),
      "age" -> new JsonNumber(age),
      "alive" -> new JsonBoolean(alive),
      "nickname" -> new JsonString(nickName.get)
    ).stringify
}

Family

class Family(surName: String, mother: Person, father: Person, children: List[Person]) extends Json {
  override def stringify = new JsonObject(
    "surName" -> new JsonString(surName),
    "mother" -> mother,
    "father" -> father,
    "children" -> new JsonArray(children: _*)
  ).stringify
}

Now let's put it all together.

val homer = new Person(name = "Homer", age = 37, alive = true, nickName = Some("Mr. Sparkle"))
val marge = new Person(name = "Marge", age = 34, alive = true, nickName = None)
val bart = new Person(name = "Bart", age = 10, alive = true, nickName = Some("El Barto"))
val lisa = new Person(name = "Lisa", age = 8, alive = true, nickName = None)
val maggie = new Person(name = "Maggie", age = 1, alive = true, nickName = None)

val simpsons = new Family(
  surName = "Simpson",
  mother = marge,
  father = homer,
  children = List(bart, lisa, maggie)
)

println(simpsons.stringify)

Output

{"surName": "Simpson", "mother": {"name": "Marge", "age": 34, "alive": true}, "father": {"name": "Homer", "age": 37, "alive": true, "nickname": "Mr. Sparkle"}, "children": [{"name": "Bart", "age": 10, "alive": true, "nickname": "El Barto"}, {"name": "Lisa", "age": 8, "alive": true}, {"name": "Maggie", "age": 1, "alive": true}]}

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages