0

So, I have a case class as well as readers and writers for both JSON and BSONDocument format.

Problem is, when inserting to MongoDB, I want to be able to specify the BSONObjectID, so I can return it upon creation. However, if I add a id: BSONObjectID in the case class, I cannot find a way to get the JSON validation/transformation to work.

This is my code:

case class Mini(username: String, email: String, quizAnswer1: List[String] )

implicit object MiniWriter extends BSONDocumentWriter[Mini] {
  def write(mini: Mini): BSONDocument = BSONDocument(
    "username" -> mini.username,
    "email" -> mini.email,
    "quizAnswer1" -> mini.quizAnswer1
  )
}

implicit object MiniReader extends BSONDocumentReader[Mini] {
  def read(doc: BSONDocument): Mini = Mini(
    doc.getAs[String]("username").get,
    doc.getAs[String]("email").get,
    doc.getAs[List[String]]("quizAnswer1").toList.flatten
  )
}

implicit val miniReads: Reads[Mini] = (
  (JsPath \ "username").read[String] and
  (JsPath \ "email").read[String] and
  (JsPath \ "quizAnswer1").read[List[String]]
)(Mini.apply _)

implicit val miniWrites: Writes[Mini] = (
  (JsPath \ "username").write[String] and
  (JsPath \ "email").write[String] and
  (JsPath \ "quizAnswer1").write[List[String]]
)(unlift(Mini.unapply))

I really want to avoid working with duplicate model representations of the same model. Any ideas?

4

2 に答える 2

0

play を使用すると、play の json fomrat/read/write を直接使用できます。

https://www.playframework.com/documentation/2.3.x/ScalaJsonCombinators

例は次のようになります。

object Mini {
    implicit val miniFormat: Format[Mini] = Json.format[Mini]
}

私が知る限り、id オブジェクトは '_id' で宣言する必要があります。

case class Mini(_id:BSONObjectId, username: String, email: String, quizAnswer1: List[String] )

BSONObjectId の暗黙的な変換には、次の形式を使用できます。

implicit object BSONObjectIDFormat extends Format[BSONObjectID] {
def writes(objectId: BSONObjectID): JsValue = {
  Json.obj("$oid" -> 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 JsObject(Seq((_, oid))) =>
    reads(oid)

  case _ => JsError("Expected BSONObjectID as JsString")
}

}

于 2015-01-16T07:05:28.257 に答える