Play 2 / Scala - Generic Reactive Mongo CRUD - json序列化

时间:2015-11-08 11:06:30

标签: json scala playframework-2.0 crud reactivemongo

我发现了一些与我的问题非常接近的问题(例如Play Framework / Scala: abstract repository and Json de/serialization),但它们并没有解决我的问题。

我想要实现的是我的CRUD DAO抽象用于普通的crud操作。

我为此构建了一个GenericMongoDaoActor:

abstract class GenericMongoDaoActor[T <: Entity: Writes](implicit inj:Injector, implicit val f:Format[T]) extends Actor with Injectable {
  protected val db = inject[DefaultDB]
  protected val collectionName: String
  protected val collection:JSONCollection

  //set to None to use fallback
  def defaultSelector(obj:T):Option[JsObject] = None
  def fallbackSelector(obj:T) = Json.obj("_id" -> Json.obj("$elemMatch" -> obj._id))

  protected def find(jsObject: JsObject) = {
    val currentSender = sender
    val futureOption = collection
      .find(jsObject)
      .cursor[T](ReadPreference.primaryPreferred)
      .headOption

    futureOption.mapTo[Option[T]].flatMap {
      case Some(pobj) =>
        currentSender ! Some(pobj)
        Future{pobj}
      case None =>
        currentSender ! None
        Future{None}
    }
  }

  protected def save(obj:T):Unit = {
    update(obj, true)
  }

  protected def update(obj:T):Unit = {
    update(obj, false)
  }

  private def update(obj:T, upsert: Boolean):Unit = {
    val selector = defaultSelector(obj) match {
      case None => fallbackSelector(obj)
      case Some(sel) => sel
    }
    collection.update(
      selector,
      obj,
      GetLastError.Default,
      upsert).onComplete {
      case Failure(e) => Logger.error("[" + this.getClass.getName + "] Couldn`t update " + obj.getClass.getName + ": " + Json.prettyPrint(Json.toJson(obj)), e)
      case Success(lastError) => //currentSender ! lastError todo: do something with lastError
    }
  }

  def findAll() = {
    collection.find(Json.obj()).cursor[T](ReadPreference.primaryPreferred).collect[List]()
  }

}

DAOActor处理继承抽象类“Entity”的实体:

abstract class Entity {
  val _id: BSONObjectID
}

目前有2个类继承实体..

正如您所看到的,我的DOAActor已经在上下文中绑定了范围内的Writes [T] ..

abstract class GenericMongoDaoActor[T <: Entity: Writes]

当我尝试构建我的项目时,它抱怨没有给出在更新方法中序列化类型为“T”的“obj”的OWrites。

No Json serializer as JsObject found for type T. Try to implement an implicit OWrites or OFormat for this type.

collection.update( <-------------

我无法找到解决此问题的方法。如果可以,请告诉我。

2 个答案:

答案 0 :(得分:0)

当我从早期版本的ReactiveMongo迁移时,我遇到了类似的问题。对我来说有用的是在ReactiveMongo API的各种调用中围绕一些.as[JsObject]次转换。

所以,如果我之前:

 collection.update(
  selector,
  obj,
  ...
)

我将其替换为:

collection.update(
  selector,
  obj.as[JsObject],
  ...
)

这似乎已经足够了,虽然我以稍微不同的方式提供必要的JSON转换器;我的抽象类的子类必须实现implicit val fmt:Format[T]成员。我怀疑这是否重要,但这似乎是一种方法: - )

答案 1 :(得分:-1)

您需要使用OWrites和OFormat而不是Writes和Format。 我知道OWrites扩展了Writes和OFormat扩展格式,但你正在使用的reactivemongo版本正在等待OWrites和OFormat,而不是它的超类型。