两位作家之间的可见性

时间:2014-04-22 10:02:40

标签: scala

在为这两个模型编写编写器时,我收到错误。

以下是我的模特:

case class Ad (
    var id: Long,
    var account: Account,
    ...
    var pictures: List[Picture]) extends Model

object Ad {
    implicit val adWrites = Json.writes[Ad]
}

case class Picture(
    var id: Long,
    var ad: Ad) extends Model

object Picture {
    implicit pictureWrites = Json.writes[Picture]

    implicit def listPictureWrites[PictureScala](implicit fmt: Writes[PictureScala]): Writes[List[PictureScala]] = new Writes[List[PictureScala]] {
        def writes(ts: List[PictureScala]) = JsArray(ts.map(t => Json.toJson(t)(fmt)))
    }
}

这不起作用。我收到了以下消息:在pictureWrites(=>“没有可用于models.AdScala的隐式写入。”)和adWrites(=>“没有针对java.util.List [models.PictureScala的隐式写入]可用。 “)。

我认为这是因为每个编写者都需要其他case类的write方法。但是我该如何解决这个问题呢?如果我对“广告”和“图片”进行评论,则可以正常使用。

1 个答案:

答案 0 :(得分:1)

Json.writes宏在这种情况下不起作用,因为你的类型是递归的。但是,明确定义Writes个实例并不算太糟糕:

import play.api.libs.functional.syntax._
import play.api.libs.json._

// Next two lines for the sake of a complete working example.
trait Model
type Account = String

case class Ad (
  var id: Long,
  var account: Account,
  var pictures: List[Picture]
) extends Model

object Ad {
  implicit val adWrites: Writes[Ad] = (
    (__ \ 'id).write[Long] and
    (__ \ 'account).write[Account] and
    (__ \ 'pictures).write[List[Picture]]
  )(unlift(Ad.unapply))
}

case class Picture(var id: Long, var ad: Ad) extends Model

object Picture {
  implicit val pictureWrites: Writes[Picture] = (
    (__ \ 'id).write[Long] and
    (__ \ 'ad).lazyWrite(Ad.adWrites)
  )(unlift(Picture.unapply))
}

然后:

scala> val ad1 = Ad(1, "foo", Nil)
ad1: Ad = Ad(1,foo,List())

scala> val ad2 = Ad(2, "bar", List(Picture(1, ad1)))
ad2: Ad = Ad(2,bar,List(Picture(1,Ad(1,foo,List()))))

scala> Json.prettyPrint(Json.toJson(ad2))
res8: String = 
{
  "id" : 2,
  "account" : "bar",
  "pictures" : [ {
    "id" : 1,
    "ad" : {
      "id" : 1,
      "account" : "foo",
      "pictures" : [ ]
    }
  } ]
}

特别注意lazyWrite中的pictureWrites,这是递归所必需的。