Two months ago, I wrote about sjson-new. I was working on that again over the weekend, so here's the update.
In the earlier post, I've introduced the family tree of JSON libraries in Scala ecosystem, the notion of backend independent, typeclass based JSON codec library. I concluded that we need some easy way of defining a custom codec for it to be usable.
roll your own shapeless
In between the April post and the last weekend, there were flatMap(Oslo) 2016 and Scala Days New York 2016. Unfortunately I wasn't able to attend flatMap, but I was able to catch Daniel Spiewak's "Roll Your Own Shapeless" talk in New York. The full flatMap version is available on vimeo, so I recommend you check it out.
sbt internally uses HList for caching using sbinary:
implicit def mavenCacheToHL = (m: MavenCache) => m.name :*: m.rootFile.getAbsolutePath :*: HNil
implicit def mavenRToHL = (m: MavenRepository) => m.name :*: m.root :*: HNil
...
and I've been thinking something like an HList or Shapeless's LabelledGeneric
would be a good intermediate datatype to represent JSON object, so Daniel's talk became the last push on my back.
In this post, I will introduce a special purpose HList called LList.
LList
sjson-new comes with a datatype called LList, which stands for labelled heterogeneous list.
List[A]
that comes with the Standard Library can only store values of one type, namely A
. Unlike the standard List[A]
, LList can store values of different types per cell, and it can also store a label per cell. Because of this reason, each LList has its own type. Here's how it looks in the REPL:
scala> import sjsonnew._, LList.:*:
import sjsonnew._
import LList.$colon$plus$colon
scala> import BasicJsonProtocol._
import BasicJsonProtocol._
scala> val x = ("name", "A") :*: ("value", 1) :*: LNil
x: sjsonnew.LList.:*:[String,sjsonnew.LList.:*:[Int,sjsonnew.LNil]] = (name, A) :*: (value, 1) :*: LNil
scala> val y: String :*: Int :*: LNil = x
y: sjsonnew.LList.:*:[String,sjsonnew.LList.:*:[Int,sjsonnew.LNil]] = (name, A) :*: (value, 1) :*: LNil
Can you find String
and Int
mentioned in that long type name of x
? String :*: Int :*: LNil
is a short form of writing that as demonstrated by y
.
BasicJsonProtocol
is able to convert all LList values into a JSON object.