Skip to content

Instantly share code, notes, and snippets.

@simerplaha
Last active March 10, 2016 04:01
Show Gist options
  • Save simerplaha/430e28f28cc97effe864 to your computer and use it in GitHub Desktop.
Save simerplaha/430e28f28cc97effe864 to your computer and use it in GitHub Desktop.
Scala macro to generate a sealed trait's sub classes. This macro will generate a function (className: String, jsonString: String) => Option[A]. Depends on shapeless-argonaut.
import scala.language.experimental.macros
import scala.reflect.macros.blackbox.Context
object JsonToClassNameMapper {
def generatePatternMatcher[A](): (String, String) => Option[A] = macro generatePatternMatcherImpl[A]
def generatePatternMatcherImpl[A: c.WeakTypeTag](c: Context)(): c.Tree = {
import c.universe._
val subclasses: Set[c.universe.Symbol] = c.weakTypeOf[A].typeSymbol.asClass.knownDirectSubclasses
val cases = subclasses.map {
subClass =>
val simpleName = subClass.fullName.substring(subClass.fullName.lastIndexOf(".") + 1, subClass.fullName.length)
cq"""$simpleName => jsonString.decodeOption[${subClass.asType}]"""
}
q"""(className: String, jsonString: String) =>
className match {
case ..$cases
}
"""
}
}
////TEST////
import argonaut._, Argonaut._, Shapeless._
sealed trait Foobar
case class Foo(x: Int, fooString: String) extends Foobar
import JsonToClassNameMapper._
object SealedExampleRunner extends App {
val myJson = """{"x": 1, "fooString" :"fooString", "lanaguge" : {}}"""
val foobarMapper = generatePatternMatcher[Foobar]()
val result = foobarMapper("Foo", myJson)
println("jsonToObject:" + result)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment