Skip to content

Instantly share code, notes, and snippets.

@megri
Created January 9, 2019 14:46
Show Gist options
  • Save megri/4d3ad3f109bb90fb0e8c4c0b6a16ffc1 to your computer and use it in GitHub Desktop.
Save megri/4d3ad3f109bb90fb0e8c4c0b6a16ffc1 to your computer and use it in GitHub Desktop.
import com.lightbend.lagom.scaladsl.playjson.JsonSerializer
import reflect.macros._
object JsonSerializerImpl {
/**
* Generates a list of JsonSerializers for all direct subtypes of type T. Every subtype needs an implicit Format[T]
* in scope at the place of expansion.
* @param c
* @tparam T
* @return
*/
def generateJsonSerializersFor[T: c.WeakTypeTag](c: blackbox.Context): c.Expr[List[JsonSerializer[_]]] = {
import c.universe._
val rootSymbol = symbolOf[T]
if (!rootSymbol.isClass)
c.abort(c.enclosingPosition, "error: not a class")
else if (!rootSymbol.asClass.isSealed)
c.abort(c.enclosingPosition, "error: not sealed")
else {
val jsonSerializers = rootSymbol.asClass.knownDirectSubclasses.map{ subclassSymbol =>
val format = q"implicitly[_root_.play.api.libs.json.Format[$subclassSymbol]]"
val classTag = q"_root_.scala.reflect.ClassTag(classOf[$subclassSymbol])"
q"_root_.com.lightbend.lagom.scaladsl.playjson.JsonSerializer($classTag, $format)"
}
c.Expr[List[JsonSerializer[_]]](q"_root_.scala.collection.immutable.List(..$jsonSerializers)")
}
}
}
// Compile in a separate compilation unit (another project basically)
//
// Usage:
// override val serializers =
// generateJsonSerializersFor[EventsRootTrait] ++ generateJsonSerializersFor[CommandsRootTrait]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment