sql >> データベース >  >> NoSQL >> MongoDB

Play:MongoDBとの間でJSONの書き込み/読み取り中にJSONを変換する方法

    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キーの値を_id \ $oidに移動することを意味しました これは

    で達成できます
    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)
    

    JsValueタイプ階層からオブジェクトを操作しているため、現時点ではBSONObjectIDを含めることはできません。 jsonをreactivemongoに渡すと、BSONValueに変換されます。 JsObjectはBSONDocumentに変換されます。 JsObjectに_id\$oidのパスが含まれている場合 このパスは自動的にBSONObjectIdに変換され、mongodbにObjectIDとして保存されます。



    1. Gorillaセッションのカスタムバックエンドを使用する利点は何ですか?

    2. MongoDBへの接続はprocess.exit()で自動的に閉じられますか?

    3. .insertOneは関数ではありません

    4. マングースでObjectIdを生成するにはどうすればよいですか?