I have a Scala reflection Symbol.
val symbol = scala.reflect.api.Symbol
how can I cast an object
val obj: Any
to the type of that Symbol ?
reason why I am asking is that I have a implicit method to convert Map[String, Any] to a Scala case class, but in side I want to to cast on each field.
TODO part is the place I want to cast the type.
object MapStringAnyOps {
implicit class MapStringAnyOps(m: Map[String, _]) {
def toCaseClass[T: TypeTag : ClassTag]: T = {
val rm = runtimeMirror(classTag[T].runtimeClass.getClassLoader)
val destType = typeOf[T]
val classTest = destType.typeSymbol.asClass
val classMirror = rm.reflectClass(classTest)
val constructor = destType.decl(termNames.CONSTRUCTOR).asMethod
val constructorMirror = classMirror.reflectConstructor(constructor)
val constructorArgs = constructor.paramLists.flatten.map((param: Symbol) => {
val paramName = param.name.toString
if (param.typeSignature <:< typeOf[Option[Any]])
m.get(paramName) **// TODO in here, I can to cast this value of Any into the proper type of this field, but I only have Symbol so I can't simply use asInstanceOf[T]**
else
m.getOrElse(paramName, throw new IllegalArgumentException("Map is missing required parameter named " + paramName))
})
try {
constructorMirror(constructorArgs: _*).asInstanceOf[T]
} catch {
case e: java.lang.IllegalArgumentException =>
throw new java.lang.IllegalArgumentException(s"Error mapping to class constructor:\n Casting from row: ${constructorArgs.map(r => r.getClass.getName).mkString(",")}, to constructor: ${constructor.paramLists.flatten.map(r => r.typeSignature.toString).mkString(",")}", e)
}
}
}
}
You can't cast.
In order to cast
.asInstanceOf[T]you need to knowTat compile time. But you know the symbol at runtime. You can do something later (e.g. at runtime) based on the information you get earlier (e.g. at compile time) if you persist somehow the information. But you can't cast earlier (i.e. at compile time) based on the information you get later (i.e. at runtime).But actually you don't need to cast.
constructorMirroracceptsAny*.Just in case, you could cast if you knew the type at compile time, e.g. if you used compile-time reflection (i.e. macros) rather than runtime reflection
By the way, you can convert a
Mapto a case class and back using librariesIn Shapeless there is a type class
ToMapconverting a case class to aMapbut the type classFromMapconverts aMapintoHListrather than case class, that's why we needfromMapmethod.How to use shapeless to convert generic Map[String, Any] to case class inside generic function?
Shapeless code to convert Map[String, Any] to case class cannot handle optional substructures
Converting Map[String,Any] to a case class using Shapeless
How to convert generic potentially nested map Map[String, Any] to case class using any library in Scala?
Scala macros for nested case classes to Map and other way around
Converting nested case classes to nested Maps using Shapeless
Convert Nested Case Classes to Nested Maps in Scala
Case class to map in Scala
Scala: convert map to case class