Search code examples
scalagenericsplayframework

Scala parsing generic type is a pain


Because I save data as json in Redis, when I get it from another services, I need to parse the json as service type. I'll let an example which works:

case class Item(id: Int, name: String)
object Item {
  import play.api.libs.json._

  implicit val read = Json.reads[Item]
  implicit val write = Json.writes[Item]

  def tupled = (Item.apply _).tupled
}


object RedisService {
 ...

 def get(key: String): Option[JsValue] =
   client.get(key).map(Json.parse(_))
}


object Service1 {
  val data = RedisService.get("service1")
  data match {
    case Some(json) => val items = json.as[List[Item]]
    case None =>
  }
}

..
object Service9 {
  val data = RedisService.get("service9")
  data match {
    case Some(json) => val items = json.as[List[Item]]
    case None =>
  }
}

optimized type (what I'm trying but get implicits error)

object RedisService {
 ...

 def get[A](key: String): Option[A] =
   client.get(key).map(x => Json.parse(x).as[A]) // no implicits found for parameter Reads[A]
}

object Service1 {
  val data = RedisService.get[List[Item]]("service1")
  data match {
    case Some(items) => // avoid using conversion in all services
    case None =>
  }
}

Solution

  • To fix your compiler error you need to add that implicit parameter to the definition of get i.e.

    def get[A](key: String)(implicit format: Reads[A]): Option[A] = ...
    

    Then for whatever actual type A the caller just needs to have the implicit Reads[A] available