这是一个我想要写入/读取MongoDB的简单JSON:
{ "id": "ff59ab34cc59ff59ab34cc59", "name": "Joe", "surname": "Cocker" }
将其存储在MongoDB中之前,"ff59ab34cc59ff59ab34cc59"
必须被转换成一个ObjectID
和id
更名为_id
...所以获得以下几方面Reads
,我怎么做到这一点?
val personReads: Reads[JsObject] = ( (__ \ 'id).read[String] ~ // how do I rename id to _id AND transform "ff59ab34cc59ff59ab34cc59" to an ObjectID? (__ \ 'name).read[String] ~ (__ \ 'surname).read[String] ) reduce
当然,我还需要为我的相反Writes
,即重命名_id
,以id
和转化的ObjectID
,格式为纯文本"ff59ab34cc59ff59ab34cc59"
.
JsonExtensions
我的应用程序中通常有一个JsExtensions对象,如下所示:
import reactivemongo.bson.BSONObjectID object JsonExtensions { import play.api.libs.json._ def withDefault[A](key: String, default: A)(implicit writes: Writes[A]) = __.json.update((__ \ key).json.copyFrom((__ \ key).json.pick orElse Reads.pure(Json.toJson(default)))) def copyKey(fromPath: JsPath,toPath:JsPath ) = __.json.update(toPath.json.copyFrom(fromPath.json.pick)) def copyOptKey(fromPath: JsPath,toPath:JsPath ) = __.json.update(toPath.json.copyFrom(fromPath.json.pick orElse Reads.pure(JsNull))) def moveKey(fromPath:JsPath, toPath:JsPath) =(json:JsValue)=> json.transform(copyKey(fromPath,toPath) andThen fromPath.json.prune).get }
对于一个简单的模型
case class SOUser(name:String,_id:BSONObjectID)
你可以像这样写你的json序列化器/反序列化器:
object SOUser{ import play.api.libs.json.Format import play.api.libs.json.Json import play.modules.reactivemongo.json.BSONFormats._ implicit val soUserFormat= new Format[SOUser]{ import play.api.libs.json.{JsPath, JsResult, JsValue} import JsonExtensions._ val base = Json.format[SOUser] private val publicIdPath: JsPath = JsPath \ 'id private val privateIdPath: JsPath = JsPath \ '_id \ '$oid def reads(json: JsValue): JsResult[SOUser] = base.compose(copyKey(publicIdPath, privateIdPath)).reads(json) def writes(o: SOUser): JsValue = base.transform(moveKey(privateIdPath,publicIdPath)).writes(o) } }
这是你在控制台中得到的:
scala> import reactivemongo.bson.BSONObjectID import reactivemongo.bson.BSONObjectID scala> import models.SOUser import models.SOUser scala> import play.api.libs.json.Json import play.api.libs.json.Json scala> scala> val user = SOUser("John Smith", BSONObjectID.generate) user: models.SOUser = SOUser(John Smith,BSONObjectID("52d00fd5c912c061007a28d1")) scala> val jsonUser=Json.toJson(user) jsonUser: play.api.libs.json.JsValue = {"name":"John Smith","id":"52d00fd5c912c061007a28d1","_id":{}} scala> Json.prettyPrint(jsonUser) res0: String = { "name" : "John Smith", "id" : "52d00fd5c912c061007a28d1", "_id" : { } } scala> jsonUser.validate[SOUser] res1: play.api.libs.json.JsResult[models.SOUser] = JsSuccess(SOUser(John Smith,BSONObjectID("52d00fd5c912c061007a28d1")),/id)
将此应用于您的示例
val _personReads: Reads[JsObject] = ( (__ \ 'id).read[String] ~ (__ \ 'name).read[String] ~ (__ \ 'surname).read[String] ).reduce
默认情况下不编译,我猜你打算写:
val _personReads: Reads[(String,String,String)] = ( (__ \ 'id).read[String] ~ (__ \ 'name).read[String] ~ (__ \ 'surname).read[String] ).tupled
在这种情况下,您可以执行以下操作
import play.api.libs.json._ import play.api.libs.json.Reads._ import play.api.libs.functional.syntax._ import play.modules.reactivemongo.json.BSONFormats._ import reactivemongo.bson.BSONObjectID def copyKey(fromPath: JsPath,toPath:JsPath ) = __.json.update(toPath.json.copyFrom(fromPath.json.pick)) val json = """{ "id": "ff59ab34cc59ff59ab34cc59", "name": "Joe", "surname": "Cocker" }""" val originaljson = Json.parse(json) val publicIdPath: JsPath = JsPath \ 'id val privateIdPath: JsPath = JsPath \ '_id \ '$oid val _personReads: Reads[(BSONObjectID,String,String)] = ( (__ \ '_id).read[BSONObjectID] ~ (__ \ 'name).read[String] ~ (__ \ 'surname).read[String] ).tupled val personReads=_personReads.compose(copyKey(publicIdPath,privateIdPath)) originaljson.validate(personReads) // yields res5: play.api.libs.json.JsResult[(reactivemongo.bson.BSONObjectID, String, String)] = JsSuccess((BSONObjectID("ff59ab34cc59ff59ab34cc59"),Joe,Cocker),/id)
或者你的意思是你想要移动_id \ $oid
可以完成的id键的值
import play.api.libs.json._ import play.api.libs.json.Reads._ import play.api.libs.functional.syntax._ import play.modules.reactivemongo.json.BSONFormats._ import reactivemongo.bson.BSONObjectID def copyKey(fromPath: JsPath,toPath:JsPath ) = __.json.update(toPath.json.copyFrom(fromPath.json.pick)) val json = """{ "id": "ff59ab34cc59ff59ab34cc59", "name": "Joe", "surname": "Cocker" }""" val originaljson = Json.parse(json) val publicIdPath: JsPath = JsPath \ 'id val privateIdPath: JsPath = JsPath \ '_id \ '$oid originaljson.transform(copyKey(publicIdPath,privateIdPath) andThen publicIdPath.json.prune)
您现在不能拥有BSONObjectID,因为您正在从JsValue类型层次结构中操作对象.当您将json传递给reactivemongo时,它将转换为BSONValue.JsObject将转换为BSONDocument.如果JsObject包含_id\$oid
此路径的路径将自动转换为BSONObjectId,它将作为ObjectID存储在mongodb中.