1

I've seen examples of how to do the conversion of a Map[String,String] such as ("id"->"1", "name"->"andre") to a case class User(id:String,name:String), but they involve calling a method mapToUser - for example:

val r = User.mapToUser(u.get)
      println("information for " + r.name + " with id " + r.id)

case class User(id: String, name: String)

object User {
  implicit def userToMap(user: User): Map[String, String] = {
    Map("id" -> user.id, "name" -> user.name)
  }

  implicit def mapToUser(m: Map[String, String]) : User = {
    User(m.get("id").get, m.get("name").get)
  }

  def unapply(arg: Map[String,String]): User = User(arg.get("id").get, arg.get("name").get)
}

Scala understands well on how to use the first implicit conversion of User to Map[String,String] has I don't have to call userToMap but don't understand why it's failing doing the conversion like for example var r = u.get.asInstanceOf[User]. It says it can't cast the value to User - I tried .to[User] also and that says

Error:(73, 24) User takes no type parameters, expected: one val r = u.get.to[User]

Full code:

import scredis._

import scala.concurrent.Future
import scala.util.{Failure, Success}

case class User(id: String, name: String)

object User {
  implicit def userToMap(user: User): Map[String, String] = {
    Map("id" -> user.id, "name" -> user.name)
  }

  implicit def mapToUser(m: Map[String, String]) : User = {
    User(m.get("id").get, m.get("name").get)
  }

  def unapply(arg: Map[String,String]): User = User(arg.get("id").get, arg.get("name").get)
}

object RedisClient {

  val redis = new Redis(host="192.168.122.2", passwordOpt = Some("privatemachine"))

  import redis.dispatcher

  def save(key:String, x : User) : Unit = {
    x.foreach {
      f => redis.hSet(key, f._1, f._2).onComplete{
        case Success(content) => None
        case Failure(e) => e.printStackTrace()
      }
    }
  }

  def get(key:String) : Future[Option[Map[String,String]]] = {
    val result = redis.hGetAll(key)

    result.onComplete {
      case Success(content) => {
        println(" --> " + content)
      }
      case Failure(e) => e.printStackTrace()
    }

    result
  }
}

object Run extends App {

  val redis = new Redis(host="192.168.122.2", passwordOpt = Some("privatemachine"))

  import redis.dispatcher


  redis.hSet("my-hash", "maker", "BMW")

  redis.hGetAll("my-hash") onComplete {
      case Success(content) => {
        println(content)
      }
      case Failure(e) => e.printStackTrace()
  }

  val u1 = User("1", "andre")
  RedisClient.save("user_1", u1)

  val userResult = RedisClient.get("user_1")
  userResult.map {
    u =>
      //val r = User.mapToUser(u.get)
      val r = u.get.to[User]
      println("information for " + r.name + " with id " + r.id)
  }.onFailure{ case x => println("Look here : " + x )}

}
Tzach Zohar
  • 37,442
  • 3
  • 79
  • 85
Fernando André
  • 1,213
  • 3
  • 19
  • 32
  • 1
    You shouldn't use casting (`.to[User]`) - just define `r`'s type explicitly to be `User` and implicit conversion would be able to convert `u.get` (which I assume is a `Map[String, String]`) into `User`: `val r: User = u.get` – Tzach Zohar Sep 13 '17 at 18:19
  • that solved it, do you care to commit this as an answer? – Fernando André Sep 13 '17 at 18:23

1 Answers1

1

You don't have to call any of the implicit methods explicitly, nor should you use casting. Implicit conversions can be applied simply by trying to assign an instance of one type into a variable/value of another type given the matching conversion.

So in your case, using these conversions would be done as follows:

val map = Map("id" -> "1", "name" -> "2")
val u: User = map // implicit conversion into User
val m: Map[String, String] = u // implicit conversion back into Map
Tzach Zohar
  • 37,442
  • 3
  • 79
  • 85