MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

Play:Jak przekształcić JSON podczas pisania/odczytywania go do/z MongoDB

JsonExtensions

Zwykle w mojej aplikacji mam obiekt JsExtensions, który wygląda następująco :

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
}

Dla prostego modelu

case class SOUser(name:String,_id:BSONObjectID)

możesz napisać swój serializator/deserializator json w ten sposób:

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)
  }
}

oto, co dostajesz w konsoli:

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)

Zastosuj to do swojego przykładu

val _personReads: Reads[JsObject] = (
  (__ \ 'id).read[String] ~
  (__ \ 'name).read[String] ~
  (__ \ 'surname).read[String]
).reduce

Nie kompiluje się domyślnie, chyba chodziło Ci o napisanie :

val _personReads: Reads[(String,String,String)] = (
  (__ \ 'id).read[String] ~
  (__ \ 'name).read[String] ~
  (__ \ 'surname).read[String]
).tupled

w takim przypadku możesz wykonać następujące czynności

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)

lub chciałeś przenieść wartość klucza id do _id \ $oid co można osiągnąć za pomocą

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)

Na razie nie możesz mieć tam BSONObjectID, ponieważ manipulujesz obiektem z hierarchii typu JsValue. Kiedy przekazujesz json do reactivemongo, jest on konwertowany na BSONValue. JsObject zostanie przekonwertowany na BSONDocument. jeśli JsObject zawiera ścieżkę do _id\$oid ta ścieżka zostanie automatycznie przekonwertowana na BSONObjectId i będzie przechowywana jako ObjectID w mongodb.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Węzeł referencyjny typu Mongodb

  2. Przechowywanie obrazów:MongoDb a system plików

  3. Ogranicz liczbę zwrotów pól z mongodb w Meteor

  4. Zwróć cały dokument z agregacji

  5. MongoDB nie działa w Vagrant Centos Box