-
-
Save mwiewior/872259b8dc3860d0c5f554a6fb0099ed to your computer and use it in GitHub Desktop.
Scala macro to convert between a case class instance and a Map of constructor parameters. Developed by Jonathan Chow (see http://blog.echo.sh/post/65955606729/exploring-scala-macros-map-to-case-class-conversion for description and usage). This version simply updates Jonathan's code to Scala 2.11.2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import scala.language.experimental.macros | |
import scala.reflect.macros.blackbox.Context | |
trait Mappable[T] { | |
def toMap(t: T): Map[String, Any] | |
def fromMap(map: Map[String, Any]): T | |
} | |
object Mappable { | |
implicit def materializeMappable[T]: Mappable[T] = macro materializeMappableImpl[T] | |
def materializeMappableImpl[T: c.WeakTypeTag](c: Context): c.Expr[Mappable[T]] = { | |
import c.universe._ | |
val tpe = weakTypeOf[T] | |
val companion = tpe.typeSymbol.companion | |
val fields = tpe.decls.collectFirst { | |
case m: MethodSymbol if m.isPrimaryConstructor => m | |
}.get.paramLists.head | |
val (toMapParams, fromMapParams) = fields.map { field => | |
val name = field.asTerm.name | |
val key = name.decodedName.toString | |
val returnType = tpe.decl(name).typeSignature | |
(q"$key -> t.$name", q"map($key).asInstanceOf[$returnType]") | |
}.unzip | |
c.Expr[Mappable[T]] { q""" | |
new Mappable[$tpe] { | |
def toMap(t: $tpe): Map[String, Any] = Map(..$toMapParams) | |
def fromMap(map: Map[String, Any]): $tpe = $companion(..$fromMapParams) | |
} | |
""" } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment