Scala + Reactivemongo:控制REST-API的自定义读取器/写入器



我正在开发一个用scala实现的REST-API,并使用reactivemongo。我的持久模型是使用case类实现的,瘦存储库层使用通过DocumentReader/DocumentWriter(通过case类伴侣对象中的隐式转换器)进行bson<->类映射的通用方法。

case class Address(street: String, number: String, city: String, zip: String)
object Address{
implicit val addressHandler = Macros.handler[Address]
implicit val addressFmt = Json.format[Address]
}

第一个格式化器将bson映射为case类,第二个格式化器将转换为json (REST-API的输出格式)。

这一切都很好,我很高兴所有的东西都很好地集成在一起。

在许多情况下,我不需要操作域对象(case类实例),只是想将来自数据库的数据写入http响应。在这些场景中,所有中间转换都是开销。我还想控制哪些字段是公开的(我曾经在Java项目中使用Yoga和Jackson)。

可能的解决方案是:

  • 有一个通用的存储库,它可以简单地转换为Map结构作为中间格式。
  • 控制驱动程序在每个查询基础上可用的隐式转换器,并为不同的"视图"编写case类
  • 使用BSONDocument作为中间格式,通过BSON =>字符串转换使REST层理解BSON。

我想知道最好的方法是什么,如果有人有这种特殊情况的经验。也许我甚至错过了另一个好的选择?

要控制公开哪些字段,可能需要编写一个Readers和Writers。下面是从这个项目中提取的一个例子https://github.com/luongbalinh/play-mongo。

import java.time.ZonedDateTime
case class User(override val id: Option[Long] = None,
            firstName: String,
            lastName: String,
            age: Int,
            active: Boolean,
            createdDate: Option[ZonedDateTime] = None,
            updatedDate: Option[ZonedDateTime] = None
             ) extends IdModel[User] {
  override def withNewId(id: Long): User = this.copy(id = Some(id))
}
object User {
import play.api.libs.functional.syntax._
import play.api.libs.json._
implicit val userReads: Reads[User] = (
(JsPath  "id").readNullable[Long] and
  (JsPath  "firstName").read[String] and
  (JsPath  "lastName").read[String] and
  (JsPath  "age").read[Int] and
  (JsPath  "active").read[Boolean] and
  (JsPath  "createdDate").readNullable[ZonedDateTime] and
  (JsPath  "updatedDate").readNullable[ZonedDateTime]
)(User.apply _)
implicit val userWrites: Writes[User] = (
(JsPath  "id").writeNullable[Long] and
  (JsPath  "firstName").write[String] and
  (JsPath  "lastName").write[String] and
  (JsPath  "age").write[Int] and
  (JsPath  "active").write[Boolean] and
  (JsPath  "createdDate").writeNullable[ZonedDateTime] and
  (JsPath  "updatedDate").writeNullable[ZonedDateTime]
)(unlift(User.unapply))
}

最新更新