JSON Encoding and Decoding in Scala with Play JSON

This is something I’ve had to look up a few times, so I figured it’s time to write up something to ease the next time a bit.

First we need to include the Play JSON library itself to build.sbt

name := """minimal-scala"""
version := "1.0"
scalaVersion := "2.11.7"
libraryDependencies += "com.typesafe.play" %% "play-json" % "2.5.13"
view raw build.sbt hosted with ❤ by GitHub

Using case classes seems to be the most used method of holding data to be encoded in JSON. So the next step is to configure out case class InventoryItem for reading and writing (decoding / encoding) into JSON with a companion object.

object InventoryItem {
implicit val inventoryItemWrites: Writes[InventoryItem] = (
(JsPath \ "name").write[String] and
(JsPath \ "serialNumber").write[String] and
(JsPath \ "value").write[Float]
)(unlift(InventoryItem.unapply))
implicit val inventoryItemReads: Reads[InventoryItem] = (
(JsPath \ "name").read[String] and
(JsPath \ "serialNumber").read[String] and
(JsPath \ "value").read[Float]
)(InventoryItem.apply _)
}
case class InventoryItem(name: String, serialNumber: String, value: Float) {}

I’m using an example where we write a list of InventoryItems into JSON. Play JSON knows how to handle Lists automatically so no configuration is needed for that.

object WritingJson extends App {
var inventory = List[InventoryItem]()
inventory = inventory :+ InventoryItem("Name", "SR-001", 33.0)
val json = Json.toJson(inventory)
println(Json.stringify(json))
}

List of IntentoryItems would like something like this in JSON.

[
{
"name": "Item",
"serialNumber": "asdsad",
"value": 22
},
{
"name": "Another Item",
"serialNumber": "SRS-001",
"value": 33
}
]

Reading JSON is from a string is a bit more involved than writing it.

object ReadingJson extends App {
var inventory: List[InventoryItem] = List()
val itemJsonString = Source.fromFile("D:\\Path\\To\\My.json").mkString
val json = Json.parse(itemJsonString)
json.validate[List[InventoryItem]] match {
case s: JsSuccess[List[InventoryItem]] => inventory = s.get
case e: JsError => println("Oh dog, what done")
}
}