Skip to content

Instantly share code, notes, and snippets.

@arosien
Last active December 28, 2015 13:28
Show Gist options
  • Save arosien/7507442 to your computer and use it in GitHub Desktop.
Save arosien/7507442 to your computer and use it in GitHub Desktop.
Conversion from shapeless records to json4s JValues.
trait JSONRecords {
import scala.annotation.implicitNotFound
import org.json4s._
import shapeless._
import shapeless.record._
import shapeless.ops.hlist._
import shapeless.ops.record._
import shapeless.syntax._
import shapeless.syntax.singleton._
object toJField extends Poly1 {
implicit def caseLong[K <: String] = at[(K, Long)](kv => JObject(JField(kv._1, JInt(kv._2))))
implicit def caseString[K <: String] = at[(K, String)](kv => JObject(JField(kv._1, JString(kv._2))))
implicit def caseOptionString[K <: String] = at[(K, Option[String])](kv => JObject(JField(kv._1, kv._2.fold(JNothing: JValue)(JString(_)))))
implicit def caseJField[K <: String, V <% JValue] = at[(K, V)](kv => JObject(JField(kv._1, kv._2)))
@implicitNotFound("\nYour record contains an unsupported key or value type.\nKeys must be a String.\nValues must be a: Long, String, Option[String]\nA quick workaround is to 'import org.json4s.JsonDSL._' in your scope.")
type Mapper[OutZ <: HList, OutM <: HList] = Mapper.Aux[toJField.type, OutZ, OutM]
}
object combine extends Poly {
implicit def caseJObject = use((f1: JObject, f2: JObject) => JObject(f1.obj ::: f2.obj))
}
def toJValue[L <: HList, K <: HList, V <: HList, OutZ <: HList, OutM <: HList](l : L)
(implicit
keys: Keys.Aux[L, K],
values: Values.Aux[L, V],
zipper: Zip.Aux[K :: V :: HNil, OutZ],
mapper: toJField.Mapper[OutZ, OutM],
reducer: LeftReducer[OutM, combine.type]) =
(l.keys zip l.values).map(toJField).reduceLeft(combine)
}
object examples extends JSONRecords {
import shapeless._
import shapeless.syntax.singleton._
val r =
("id" ->> 1234L) ::
("foo" ->> "bar") ::
HNil
val jvalue = toJValue(r)
// JObject(JField("id", 1234), JField("foo", "bar))
}
@rrmckinley
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment