'Get type of primitive field from an object using Scala reflection
So I am attempting to grab the types of each field in a Scala object class:
package myapp.model
object MyObject {
val theInt: Option[Int]
}
Using the ReflectionHelper so graciously provided by Brian in this post. I use getFieldType but it returns Option[Object] instead of what it is, which is Option[Int]. The example code in that answer works for a case class, for example:
package myapp.model
case class Person(
name: String,
age: Option[Int]
)
scala> ReflectionHelper.getFieldType("myapp.model.Person", "age") // int
res12: Option[reflect.runtime.universe.Type] = Some(Option[Int])
However, if I run getFieldType on a Scala object field, we get this:
scala> ReflectionHelper.getFieldType("myapp.model.MyObject$", "theInt")
res10: Option[reflect.runtime.universe.Type] = Some(Option[Object])
What is different about Scala objects that causes this behavior and how can I get getFieldType to return Option[Int] instead of Option[Object] like it does for the case class?
Here is the ReflectionHelper from the other question for convenience:
import scala.reflect.runtime.{ universe => u }
import scala.reflect.runtime.universe._
object ReflectionHelper {
val classLoader = Thread.currentThread().getContextClassLoader
val mirror = u.runtimeMirror(classLoader)
def getFieldType(className: String, fieldName: String): Option[Type] = {
val classSymbol = mirror.staticClass(className)
for {
fieldSymbol <- classSymbol.selfType.members.collectFirst({
case s: Symbol if s.isPublic && s.name.decodedName.toString() == fieldName => s
})
} yield {
fieldSymbol.info.resultType
}
}
def maybeUnwrapFieldType[A](fieldType: Type)(implicit tag: TypeTag[A]): Option[Type] = {
if (fieldType.typeConstructor == tag.tpe.typeConstructor) {
fieldType.typeArgs.headOption
} else {
Option(fieldType)
}
}
def getFieldClass(className: String, fieldName: String): java.lang.Class[_] = {
// case normal field return its class
// case Option field return generic type of Option
val result = for {
fieldType <- getFieldType(className, fieldName)
unwrappedFieldType <- maybeUnwrapFieldType[Option[_]](fieldType)
} yield {
mirror.runtimeClass(unwrappedFieldType)
}
// Consider changing return type to: Option[Class[_]]
result.getOrElse(null)
}
}
Solution 1:[1]
Try
// import scala.reflect.runtime.universe._
val loader = this.getClass.getClassLoader
runtimeMirror(loader)
.staticClass("myapp.model.Person").typeSignature
.member(TermName("age")).typeSignature // => Option[Int]
runtimeMirror(loader)
.staticModule("myapp.model.MyObject").typeSignature
.member(TermName("theInt")).typeSignature // => Option[Int]
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | ecoe |
