Scala + Reactivemongo:控制REST-API的自定义读者/编写者

时间:2015-07-30 09:15:19

标签: json scala rest reactivemongo scalatra

我正在研究在Scalatra中实现的REST-API并使用reactivemongo。我的持久模型使用案例类实现,瘦存储库层使用通过DocumentReader / DocumentWriter进行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结构转换为中间格式。
  • 基于每个查询控制驱动程序可用的隐式转换器,并为不同的“视图”编写案例类
  • 使用BSONDocument作为中间格式,并通过bson =>字符串转换使REST层了解BSON。

我想知道什么是最好的方法,如果有人对这个特定场景有一些经验。也许我甚至错过了另一个好选择?反馈非常受欢迎。

1 个答案:

答案 0 :(得分:0)

要控制暴露哪些字段,您可能需要编写读者和作者。以下是从此项目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))
}