Getting the parameters of a case class through Reflection

introspection, reflection, scala, scala-2.10

Solution

If you use Scala 2.10 reflection, this answer is half of the things you need. It will give you the method symbols of the case class, so you know the order and names of arguments:

import scala.reflect.runtime.{universe => ru}
import ru._

def getCaseMethods[T: TypeTag] = typeOf[T].members.collect {
  case m: MethodSymbol if m.isCaseAccessor => m
}.toList

case class Person(name: String, age: Int)

getCaseMethods[Person]  // -> List(value age, value name)

You can call `.name.toString` on these methods to get the corresponding method names.

The next step is to invoke these methods on a given instance. You need a runtime mirror for that

val rm = runtimeMirror(getClass.getClassLoader)

Then you can "mirror" an actual instance:

val p  = Person("foo", 33)
val pr = rm.reflect(p)

Then you can reflect on `pr` each method using `reflectMethod` and execute it via `apply`. Without going through each step separately, here is a solution altogether (see the `val value =` line for the mechanism of extracting a parameter's value):

def caseMap[T: TypeTag: reflect.ClassTag](instance: T): List[(String, Any)] = {
  val im = rm.reflect(instance)
  typeOf[T].members.collect {
    case m: MethodSymbol if m.isCaseAccessor =>
      val name  = m.name.toString
      val value = im.reflectMethod(m).apply()
      (name, value)
  } (collection.breakOut)
}

caseMap(p) // -> List(age -> 33, name -> foo)

Problem

As a follow up of Matt R's question, as Scala 2.10 has been out for quite an amount of time, what would be the best way to extract the fields and values of a case class. Taking a similar example: ``` case class Colour(red: Int, green: Int, blue: String) { val other: Int = 42 } val RBG = Colour(1,3,"isBlue") ``` I want to get a list (or array or any iterator for that matter) that would have the fields declared in the constructor as tuple values like these: ``` [(red, 1),(green, 3),(blue, "isBlue")] ``` I know the fact that there are a lot of examples on the net regarding the same issue but as I said, I wanted to know what should be the most ideal way to extract the required information

Original source

Related problems