【问题标题】:Play & ReactiveMongo: How to deserialize Json from request in controllerPlay & ReactiveMongo:如何从控制器中的请求中反序列化 Json
【发布时间】:2014-01-01 18:29:07
【问题描述】:

下面又是我在previous post... 中提出的案例类,但有cmbaxter 建议的修复:

case class User(
  id: Option[BSONObjectID],
  name: String,
  addresses: Option[List[BSONObjectID]]
)

object User {
  implicit object UserWriter extends BSONDocumentWriter[User] {
    def write(user: User) = BSONDocument(
      "_id" -> user.id.getOrElse(BSONObjectID.generate),
      "name" -> user.name,
      "addresses" -> user.addresses
    ) 
  }

  implicit object UserReader extends BSONDocumentReader[User] {
    def read(doc: BSONDocument) = User(
      doc.getAs[BSONObjectID]("_id"),
      doc.getAs[String]("name").get,
      doc.getAs[List[BSONObjectID]]("addresses")
    )
  }
}

现在我正在尝试实现一个 Play 控制器来验证传入的 Json 并将其保存到数据库 (MongoDB) 中。下面是我的代码:

object Users extends Controller with MongoController {

  private def collection = db.collection[JSONCollection]("users")

  def create = Action.async(parse.json) { request =>
    request.body.validate[User].map { user =>
      collection.insert(user).map { lastError =>
        Logger.debug(s"Successfully inserted with LastError: $lastError")
        Created
      }
    }.getOrElse(Future.successful(BadRequest("invalid json")))
  }
}

上面的代码没有编译,因为编译器没有找到任何Json反序列化器:

[error] /home/j3d/Projects/test/app/controllers/Users.scala:44: No Json deserializer found for type models.User. Try to implement an implicit Reads or Format for this type.
[error]     request.body.validate[User].map { user =>
[error]                          ^

是否可以重用我在User 伴随对象中定义的BSONDocumentWriterBSONDocumentReader,而不是实现ReadsWrites

【问题讨论】:

    标签: json mongodb scala playframework reactivemongo


    【解决方案1】:

    不,您不能将 BSON 文档读取器/写入器重用为 JSON 读取/写入。但是,您可以重用 JSON 读/写作为 BSON 文档读取器/写入器。您想使用JSONCollection 从 play-reactive-mongo-plugin 访问数据库,然后将您的 BSON 文档读取器/写入器重写为 JSON 读取/写入。您可以在 play-mongo-knockout 激活器模板中看到这样做的示例:

    https://github.com/typesafehub/play-mongo-knockout

    【讨论】:

    • Tx,很有趣。有没有很好的例子来说明如何处理列表(例如 Users.addresses)和复合元素(例如由 hashtext 和 salt 组成的密码类)?
    • 列表应该可以正常工作...例如 (__ \ "someKey").read[List[String]]。对于自定义类型,定义隐式的读/写或格式,例如:implicit lazy val fooReads: Reads[Foo] = ...,然后就可以 (__ \ "foo").read[Foo]跨度>
    • 非常感谢您的大力支持!与此同时,我[重新]阅读了“Play in Action”一书的第 8 章,其中详细介绍了这个主题 - 我读了 6 个月......但看起来我患有阿尔茨海默病 ;-)
    【解决方案2】:

    如果您仍在寻找更复杂的示例,我将在 3 小时后完成此操作。它是模型自动写入的基本实现,它使用 10 行代码验证 json 请求并存储到集合中:) 你不需要在控制器中重复插入

    https://github.com/MilosMosovsky/play-reactivemongo-models

    【讨论】:

      猜你喜欢
      • 2016-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-24
      • 2014-03-28
      • 2021-07-07
      相关资源
      最近更新 更多