14

How can I look up the value of an object's property dynamically by name in Scala 2.10.x?

E.g. Given the class (it can't be a case class):

class Row(val click: Boolean,
          val date: String,
          val time: String)

I want to do something like:

val fields = List("click", "date", "time")
val row = new Row(click=true, date="2015-01-01", time="12:00:00")
fields.foreach(f => println(row.getProperty(f)))    // how to do this?
jbrown
  • 7,518
  • 16
  • 69
  • 117
  • 1
    You have to use reflection. http://docs.scala-lang.org/overviews/reflection/overview.html – lmm Feb 11 '15 at 16:05
  • possible duplicate of [Simple Iteration over case class fields](http://stackoverflow.com/questions/23128433/simple-iteration-over-case-class-fields) – Kamil Domański Feb 11 '15 at 16:27
  • you can check my answer here to achieve this at compile time vs using runtime reflection : http://stackoverflow.com/a/28420822/1331769 – Vikas Pandya Feb 12 '15 at 04:14

2 Answers2

18
class Row(val click: Boolean,
      val date: String,
      val time: String)

val row = new Row(click=true, date="2015-01-01", time="12:00:00")

row.getClass.getDeclaredFields foreach { f =>
 f.setAccessible(true)
 println(f.getName)
 println(f.get(row))
}
Kamil Domański
  • 323
  • 3
  • 6
  • Thank you, this works like a charm for my use-case: _extract data from a class instance, when the property name is coming from somewhere else_ (an API call). Calling `.setAccessible(true)` was necessary. – kilogic Mar 02 '18 at 18:09
0

You could also use the bean functionality from java/scala:

import scala.beans.BeanProperty
import java.beans.Introspector

object BeanEx extends App { 
  case class Stuff(@BeanProperty val i: Int, @BeanProperty val j: String)
  val info = Introspector.getBeanInfo(classOf[Stuff])

  val instance = Stuff(10, "Hello")
  info.getPropertyDescriptors.map { p =>
    println(p.getReadMethod.invoke(instance))
  }
}
Rich Henry
  • 1,837
  • 15
  • 25