Skip to content

Instantly share code, notes, and snippets.

@kevinmeredith
Created January 7, 2017 18:57
Show Gist options
  • Select an option

  • Save kevinmeredith/3014ee149e0a6d8440bc43ed8c6bb734 to your computer and use it in GitHub Desktop.

Select an option

Save kevinmeredith/3014ee149e0a6d8440bc43ed8c6bb734 to your computer and use it in GitHub Desktop.
Generic Derivation of `JsonValue` from shapeless-book - my attempt
package net
import shapeless.{::, Generic, HList, HNil, Lazy}
sealed trait JsonValue
case class JsonObject(fields: List[(String, JsonValue)]) extends JsonValue
case class JsonArray(items: List[JsonValue]) extends JsonValue
case class JsonString(value: String) extends JsonValue
case class JsonNumber(value: Double) extends JsonValue
case class JsonBoolean(value: Boolean) extends JsonValue
case object JsonNull extends JsonValue
trait JsonEncoder[A] {
def encode(value: A): JsonValue
}
object JsonEncoder {
def instance[A](f: A => JsonValue): JsonEncoder[A] =
new JsonEncoder[A] {
override def encode(x: A): JsonValue = f(x)
}
implicit val doubleEncoder: JsonEncoder[Double] =
instance[Double](JsonNumber)
implicit val stringEncoder: JsonEncoder[String] =
instance[String](JsonString)
implicit val boolEncoder: JsonEncoder[Boolean] =
instance[Boolean](JsonBoolean)
implicit val nullEncoder: JsonEncoder[Null] =
instance[Null](_ => JsonNull)
implicit val hnilEncoder: JsonEncoder[HNil] =
instance[HNil](_ => JsonObject(Nil))
implicit def hlistEncoder[H, T <: HList](
implicit hEncoder: Lazy[JsonEncoder[H]],
tEncoder: JsonEncoder[T]
): JsonEncoder[H :: T] =
instance[H :: T] {
case h :: t => JsonObject( List(hEncoder.value.encode(h), tEncoder.encode(t) ) )
}
implicit def genericEncoder[A, R](
implicit gen: Generic[A] { type Repr = R },
enc: Lazy[JsonEncoder[R]]): JsonEncoder[A] =
instance[A] { a =>
enc.value.encode( gen.to(a) )
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment