reflection - Scala Map to Case Class conversion -


i'm trying convert scala map[string, any] case class using scala reflection (scala 2.11) follows -

val m = map("name" -> "abc", "age" -> 7, "gender" -> "male") case class somecc(name: string, age: int, gender: string)  import scala.reflect.classtag     def createcaseclass[t](somemap : map[string, any])(implicit someclasstag : classtag[t]) = {      val ctor = someclasstag.runtimeclass.getconstructors.head     val args = someclasstag.runtimeclass.getdeclaredfields.map(x => somemap(x.getname))         ctor.newinstance(args: _*).asinstanceof[t]   } 

this unfortunately results in compile error -

name: unknown error message: <console>:106: error: type mismatch;  found   : array[any]  required: array[_ <: object] note: >: object, class array invariant in type t. may wish investigate wildcard type such `_ >: object`. (sls 3.2.10)               ctor.newinstance(args: _*).asinstanceof[t]                            ^ 

i'm new using classtags , understand error because java.lang.object subset of , include non-java objects.

when tried replace anyref (which corresponds java.lang.object in jre), function call results in type mismatch error.

import scala.reflect.classtag     def createcaseclass[t](somemap : map[string, anyref])(implicit someclasstag : classtag[t]) = {      val ctor = someclasstag.runtimeclass.getconstructors.head     val args = someclasstag.runtimeclass.getdeclaredfields.map(x => somemap(x.getname))         ctor.newinstance(args: _*).asinstanceof[t]   }  val somecc = createcaseclass[somecc](m)  name: unknown error message: <console>:106: error: type mismatch;  found   : scala.collection.immutable.map[string,any]  required: map[string,anyref]        val somecc = createcaseclass[somecc](m) 

what's best way resolve error? suggestions appreciated. thanks!

update 1 - updating implicitly cast anyref leads error 'java.util.nosuchelementexception' on function call.

import scala.reflect.classtag import scala.reflect.runtime.universe._     def createmyclass[t](somemap : map[string, any])(implicit someclasstag : classtag[t]) = {         val ctor = someclasstag.runtimeclass.getconstructors.head         val args = someclasstag.runtimeclass.getdeclaredfields.map(x => somemap(x.getname))         ctor.newinstance(args.asinstanceof[seq[anyref]]: _*).asinstanceof[t]  }  val m = map("name" -> "abc", "age" -> 7, "gender" -> "male") case class somecc(name: string, age: int, gender: string)  createmyclass[somecc](m)  name: java.util.nosuchelementexception message: key not found: $outer stacktrace:   @ scala.collection.maplike$class.default(maplike.scala:228)   @ scala.collection.abstractmap.default(map.scala:59)   @ scala.collection.maplike$class.apply(maplike.scala:141)   @ scala.collection.abstractmap.apply(map.scala:59)   @ $$$e75186ae1b35495ffea8e318378149a$$$$anonfun$1.apply(<console>:135)   @ $$$e75186ae1b35495ffea8e318378149a$$$$anonfun$1.apply(<console>:135)   @ scala.collection.traversablelike$$anonfun$map$1.apply(traversablelike.scala:234)   @ scala.collection.traversablelike$$anonfun$map$1.apply(traversablelike.scala:234)   @ scala.collection.indexedseqoptimized$class.foreach(indexedseqoptimized.scala:33)   @ scala.collection.mutable.arrayops$ofref.foreach(arrayops.scala:186)   @ scala.collection.traversablelike$class.map(traversablelike.scala:234)   @ scala.collection.mutable.arrayops$ofref.map(arrayops.scala:186)   @ createmyclass(<console>:135) 

what doing wrong here?

use cast:

ctor.newinstance(args.asinstanceof[seq[anyref]]: _*).asinstanceof[t] 

note map every field of case class constructor param. incorrect, because case class can have fields aren't in constructor, , code break.

a better idea use scala reflection:

import reflect.runtime.universe._  def mkclassinstance[t: typetag](args: map[string, any]): t = {   val rmirror = runtimemirror(getclass.getclassloader)   val cmirror = rmirror.reflectclass(typeof[t].typesymbol.asclass)   // primary constructor first 1   val ctor = typeof[t].decl(termnames.constructor).asterm.alternatives.head.asmethod   val arglist = ctor.paramlists.flatten.map(param => args(param.name.tostring))   cmirror.reflectconstructor(ctor)(arglist: _*).asinstanceof[t] } def mkinnerclassinstance[t: typetag](outer: any)(args: map[string, any]): t = {   val rmirror = runtimemirror(getclass.getclassloader)   val cmirror = rmirror.reflect(outer).reflectclass(typeof[t].typesymbol.asclass)   // primary constructor first 1   val ctor = typeof[t].decl(termnames.constructor).asterm.alternatives.head.asmethod   val arglist = ctor.paramlists.flatten.map(param => args(param.name.tostring))   cmirror.reflectconstructor(ctor)(arglist: _*).asinstanceof[t] } 

Comments

Popular posts from this blog

android - InAppBilling registering BroadcastReceiver in AndroidManifest -

python Tkinter Capturing keyboard events save as one single string -

sql server - Why does Linq-to-SQL add unnecessary COUNT()? -