如何找到播放表单类型(用于处理控制器中的发布请求)以映射包含BSONObjectID类型的类?

时间:2015-07-02 15:32:00

标签: mongodb scala playframework reactivemongo

我正在使用Play Framework(2.2.6)/ scala / mongoDB处理Web应用程序,我遇到了reactivemongo.bson.BSONObjectID的问题。 (我是ReactiveMongo和Scala的初学者)

我的控制器包含以下代码:

val actForm = Form(tuple(
    "name" -> optional(of[String]),
    "shortcode" -> optional(of[String]),
    "ccam" -> mapping(
        "code" -> optional(of[String]),
        "description" -> optional(of[String]),
        "_id" -> optional(of[BSONObjectID])
    )(CCAMAct.apply)(CCAMAct.unapply)
));

def addAct = AsyncStack(AuthorityKey -> Secretary) { implicit request =>
    val user = loggedIn
    actForm.bindFromRequest.fold(
    errors => Future.successful(BadRequest(errors.errorsAsJson)), {
      case (name, shortcode, ccam) =>

        val newact = Json.obj(
          "id" -> BSONObjectID.generate,
          "name" -> name,
          "shortcode" -> shortcode,
          "ccam" -> ccam
        )

        settings.update(
            Json.obj("practiceId" -> user.practiceId.get),
            Json.obj("$addToSet" -> Json.obj("acts" -> Json.obj("acte" -> newact)))
        ).map { lastError => Ok(Json.toJson(newact)) }
    })
}

CCAMAct 类的定义如下:

import models.db.Indexable
import play.api.libs.json._
import reactivemongo.bson.BSONObjectID
import reactivemongo.api.indexes.{Index, IndexType}
import models.db.{MongoModel, Indexable}
import scala.concurrent.Future
import play.modules.reactivemongo.json.BSONFormats._
import models.practice.Practice
import play.api.libs.functional.syntax._

case class CCAMAct(code:Option[String],
                   description:Option[String],
                   _id: Option[BSONObjectID] = None) extends MongoModel {}

object CCAMAct extends Indexable {

    private val logger = play.api.Logger(classOf[CommonSetting]).logger

    import play.api.Play.current
    import play.modules.reactivemongo.ReactiveMongoPlugin._
    import play.modules.reactivemongo.json.collection.JSONCollection
    import scala.concurrent.ExecutionContext.Implicits.global

    def ccam: JSONCollection = db.collection("ccam")

    implicit val ccamFormat = Json.format[CCAMAct]

    def index() = Future.sequence(
        List (
            Index(Seq("description" -> IndexType.Text))
        ).map(ccam.indexesManager.ensure)
    ).onComplete { indexes => logger.info("Text index on CCAM ends") }
}

因此编译器抛出了这个错误:

Cannot find Formatter type class for reactivemongo.bson.BSONObjectID. Perhaps you will need to import play.api.data.format.Formats._
       "_id" -> optional(of[BSONObjectID])
                           ^

(当然我已经导入了“play.api.data.format.Formats ._”)

我还尝试在网络上的类似帖子中添加自定义格式化程序。

object Format extends Format[BSONObjectID] {

    def writes(objectId: BSONObjectID): JsValue = JsString(objectId.stringify)

    def reads(json: JsValue): JsResult[BSONObjectID] = json match {
        case JsString(x) => {
            val maybeOID: Try[BSONObjectID] = BSONObjectID.parse(x)
            if(maybeOID.isSuccess) 
                JsSuccess(maybeOID.get) 
            else {
                JsError("Expected BSONObjectID as JsString")
            }
        }
        case _ => JsError("Expected BSONObjectID as JsString")
    }
}

......没有任何成功。

[更新后的帖子]
最后我无法找到播放表单类型(用于处理控制器中的POST请求)以映射包含BSONObjectID类型的类...

任何人都知道解决这个问题的干净解决方案吗?

1 个答案:

答案 0 :(得分:1)

来自ReactiveMongo的BSON类型的JSON public Publisher(Jedis publisherJedis, String channels, String clusterName) { this.publisherJedis = publisherJedis; this.channels = channels; this.clusterName = clusterName; } public void start() { log.info("publishing on channel +odown"); try { while(true) { if(JedisPoolFactory.getMasterDown(clusterName)) { publisherJedis.publish("+odown", "master down, master down"); } } } catch(Exception ex) { log.error("failure with end of stream catching.", ex); } } 不是由Format中的Play本身提供,而是由Play的ReactiveMongo插件提供。

Formats._