在Play中将泛型类型T隐式转换为JsValue!骨架

时间:2017-10-19 08:52:11

标签: json scala generics playframework

我在Play 2.6应用程序中声明泛型方法时遇到问题,该方法将JSON转换为其中一个案例类模型的实例。

使用辅助对象和格式化程序声明的所有模型:

import play.api.libs.json.{Json, OFormat}
case class Shot(id: Long, likes_count: Long)
object Shot {
  implicit val format: OFormat[Shot] = Json.format[Shot]
}

val s1: Shot = Json.toJson(f).as[Shot] // Works great

def testJsonGeneric[T](js: JsValue)(implicit ev: OFormat[T]): T = {
    js.as[T](ev)
}

val s2: Shot = testJsonGeneric(Json.toJson(f)) // could not find implicit value for parameter ev: play.api.libs.json.OFormat[T]. Compilation failed

最后一行代码抛出

  

无法找到参数ev的隐含值:play.api.libs.json.OFormat [T]

但是,如果我像这样调用我的泛型方法(使用显式格式化程序),它可以正常工作:

val s2: Shot = testJsonGeneric(Json.toJson(f))(Shot.format)

但是,如果我希望我的JSON返回一个对象列表,我必须为List [Shot]定义一个额外的格式化程序,以便在默认Play的json.as [List [Shot]]可以显式传递给该方法时很容易让我用一个现有的格式化程序来完成这个,就像已经在辅助对象中定义的格式化程序一样。

那么,在我的情况下,甚至可以隐式为泛型类型T提供格式化程序吗?

谢谢

1 个答案:

答案 0 :(得分:3)

你绝对可以这样做,你只需稍微改变一下声明。

将case类和伴随声明移到方法之外,然后显式import Shot._以隐含范围:

import play.api.libs.json.{JsValue, Json, OFormat}

object Foo {
  case class Shot(id: Long, likes_count: Long)
  object Shot {
    implicit def format: OFormat[Shot] = Json.format[Shot]
  }

  def main(args: Array[String]): Unit = {
    import Shot._

    val f = Shot(1, 2)

    def testJsonGeneric[T](js: JsValue)(implicit ev: OFormat[T]): T = {
      js.as[T](ev)
    }

    val s2: Shot = testJsonGeneric(Json.toJson(f))
  }
}