I'm trying to implement (de)serialization from Scala case classes to Maps (field_name -> field_value). The problem is I don't know how to create a function, that would take a case class type and a map, instantiate, populate and return it. I've seen this done in some JSON libraries, but I don't get the code.
Doing this for a particular case class is trivial:
scala> :paste
// Entering paste mode (ctrl-D to finish)
case class Foo(x: Int, y: Double, z: String) {
def toMap = Map('x -> x, 'y -> y, 'z -> z)
}
object Foo {
def apply(vals: Map[Symbol, Any]): Foo = Foo(vals('x).asInstanceOf[Int], vals('y).asInstanceOf[Double], vals('z).asInstanceOf[String])
}
// Exiting paste mode, now interpreting.
defined class Foo
defined module Foo
scala> Foo(Map('x -> 1, 'y -> 2.0, 'z -> "wibble"))
res0: Foo = Foo(1,2.0,wibble)
scala> res0.toMap
res1: scala.collection.immutable.Map[Symbol,Any] = Map('x -> 1, 'y -> 2.0, 'z -> wibble)
But I'm guessing that you want to create something that works for any case class, where you don't necessarily know what the names of the values are?
In which case, you're going to have to take a look at reflection (added in Scala 2.10.0):
http://docs.scala-lang.org/overviews/reflection/overview.html
You can use reflection to iterate over the members of a class, find out what their names are and then create your map. For example:
scala> import reflect.runtime.universe._
import reflect.runtime.universe._
scala> typeOf[Foo].members filter { m => m.isMethod && m.asMethod.isStable }
res2: Iterable[reflect.runtime.universe.Symbol] = SynchronizedOps(value z, value y, value x)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With