lundi 14 août 2017

Scala Map to Case Class conversion

I'm trying to convert a Scala Map[String, Any] to a case class using Scala reflection (Scala 2.11) as follows -

val m = Map("name" -> "ABC", "age" -> 007, "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 a compile error -

Name: Unknown Error
Message: <console>:106: error: type mismatch;
 found   : Array[Any]
 required: Array[_ <: Object]
Note: Any >: Object, but class Array is invariant in type T.
You may wish to investigate a wildcard type such as `_ >: Object`. (SLS 3.2.10)
              ctor.newInstance(args: _*).asInstanceOf[T]
                           ^

I'm fairly new to using ClassTags and I understand that this error is primarily because java.lang.Object is a subset of Any and Any could include non-java objects.

When I tried to replace Any with AnyRef (which corresponds to java.lang.Object in JRE), the function call results in a 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 the best way to resolve this error? Suggestions appreciated. Thanks!





Aucun commentaire:

Enregistrer un commentaire