如何使用嵌套Map(带键包含嵌套case clas的名称)将Map转换为case类。
假设我们有:
case class OuterClass(fieldName1: String, fieldName2: InnerClass)
case class InnerClass(innerFieldName: Int)
如何转换:
Map("fieldName1" -> "stringValue",
"name" -> "ClassName",
"fieldName2" -> Map(
"innerFieldName" -> "value",
"innerClassName" -> "CaseClassName"))
到
OuterClass("stringValue", InnerClass("value"))
答案 0 :(得分:2)
您可以使用mirroring:
import scala.reflect.runtime.universe._
val ru = scala.reflect.runtime.universe
val m = runtimeMirror(getClass.getClassLoader)
def constructor(t: Type) = //get MethodMirror for constructor
m.reflectClass(t.typeSymbol.asClass).reflectConstructor(t.decl(nme.CONSTRUCTOR).asMethod)
def create(t: Type, inputRaw: Map[String, Any]): Any = {
val cnstrct = constructor(t)
val params = cnstrct.symbol.paramLists.flatten //get constructor params
val input = inputRaw map { //resolve internal maps
case (k: String, m: Map[String, Any]) =>
k -> create(params.find(_.name.toString == k).get.typeSignature, m)
case x => x
}
cnstrct(params.map(_.name.toString).map(input).toSeq: _*) //invoke constructor
}
scala> case class Aaa(aa: Int, bb: String)
defined class Aaa
scala> case class Zzz(a: Aaa, b: String)
defined class Zzz
scala> create(typeOf[Zzz], Map("a" -> Map("aa" -> 1, "bb" -> "2"), "b" -> "b"))
res22: Any = Zzz(Aaa(1,2),b)
请注意,您在这里不需要innerClassName
字段。如果您不知道根类的名称:
create(m.classSymbol(Class.forName("RootCaseClassName")).selfType, ...)