我有模特:
case class MyModel1(id: UUID, a: Int, b: String...)
case class MyModel2(id: Long, c: Int, d: String...)
我希望他们中的一些能够将自己转换为JSON。
trait Jsonable[T] {
import play.api.libs.json._
implicit val writer: Writes[T] = Json.writes[T]
}
trait JsonableId[TId, T] extends Jsonable[T] {
implicit val pkIdWriter = Writes[Pk[TId]] { pkId => JsString(pkId.get.toString) }
implicit val idWriter = Writes[TId] { id => JsString(id.toString) }
}
当我说:
object MyModel1 extends JsonableId[Long, MyModel1] {
def single(a: Long) = //.....
}
它会抛出错误No unapply function found
。好吧,我试着这样做:
trait Jsonable[T: {def unapply(a: T): Option[T]}] {
import play.api.libs.json._
implicit val writer: Writes[T] = Json.writes[T]
}
但错误是traits cannot have type parameters with context bound
。
我该如何处理?
答案 0 :(得分:1)
这不起作用,因为宏实现的方法Json.writes
没有关于T
的足够信息。
No unapply function found
不是唯一会收到的错误消息,它只是第一个。
如果您想使用鸭子打字,您应该使用T <: {def unapply(a: T): Option[T]}
。使用T: {def unapply(a: T): Option[T]}
,您尝试添加{def unapply(a: T): Option[T]}[T]
类型的隐式参数,这没有任何意义。
任何方式:它对您没有帮助:writesImpl
宏无法在随播对象中找到unapply
方法,而不能在T
本身找到。我想它应该更早失败,如No companion object found
或Call this method with case class name as type parameter
之类的错误。
所以答案是:不要试图这样做。只需手动添加implicit val writer: Writes[T] = Json.writes[MyModel1]
。
实现“类似这样的东西”的唯一方法是使用宏实现的注释将这样的隐式参数添加到伴随对象中,如下所示:
@withWrites case class MyModel1(id: UUID, a: Int, b: String...)
@withWrites case class MyModel2(id: Long, c: Int, d: String...)