Reactive Scala Driver for MongoDB
Asynchronous & Non-Blocking
This Play JSON library provides a JSON serialization pack for ReactiveMongo, based on Play Framework JSON library.
Setup
You can setup this serialization pack by adding the following dependency in your project/Build.scala
(or build.sbt
).
libraryDependencies ++= Seq(
"org.reactivemongo" %% "reactivemongo-play-json" % "0.11.14"
)
If the dependency for the Play plugin (with the right version) is present, it already provides the JSON support and this JSON serialization pack must not be added as a separate dependency.
Then, the following code enables this JSON serialization pack.
import reactivemongo.play.json._
Documents and values
There is one Play JSON class for most of the BSON types, all in the play.api.libs.json
package:
All these JSON types extend JsValue
, thus any JSON value can be converted to appropriate BSON value:
BSON | JSON |
---|---|
BSONDocument | JsObject |
BSONArray | JsArray |
BSONBinary | JsObject with a $binary JsString field containing the value in hexadecimal representation |
BSONBoolean | JsBoolean |
BSONDBPointer | No JSON type |
BSONDateTime | JsObject with a $date JsNumber field with the timestamp (milliseconds) as value |
BSONDouble | JsNumber |
BSONInteger | JsNumber |
BSONJavaScript | JsObject with a $javascript JsString value representing the JavaScript code |
BSONLong | JsNumber |
BSONMaxKey | No JSON type |
BSONMinKey | No JSON type |
BSONNull | No JSON type |
BSONObjectID | JsObject with a $oid JsString field with the stringified ID as value |
BSONRegex | JsObject with a $regex JsString field with the regular expression, and optionally an $options JsString field with the regex flags (e.g. "i" for case insensitive) |
BSONString | JsString |
BSONSymbol | JsObject with a $symbol JsString field with the symbol name as value |
BSONTimestamp | JsObject with a $time and a $i JsNumber fields |
BSONUndefined | No JSON type |
Furthermore, the whole library is articulated around the concept of Writes
and Reads
. These are type classes which purpose is to serialize/deserialize objects of arbitrary types into/from JSON.
Consequently, any type that can be serialized as JSON can be also be serialized as BSON.
A document is represented by JsObject
, which is basically an immutable list of key-value pairs. Since it is the most used JSON type, one of the main focuses of the ReactiveMongo Play JSON library is to manage such JsObject
s as easy as possible. The encode of such JSON object needs an instance of the typeclass OWrites
.
This library provides a specialized collection called reactivemongo.play.json.JSONCollection
that deals naturally with JsValue
and JsObject
. Thanks to it, you can now fetch documents from MongoDB in the JSON format, transform them by removing and/or adding some properties, and send them to the client.
Even better, when a client sends a JSON document, you can validate it and transform it before saving it into a MongoDB collection (coast-to-coast approach).
JSON cursors
The support of Play JSON for ReactiveMongo provides some extensions of the result cursors, as .jsArray()
to read underlying data as a JSON array.
import play.api.libs.json._
import play.api.libs.concurrent.Execution.Implicits.defaultContext
import reactivemongo.play.json._
import reactivemongo.play.json.collection.{
JSONCollection, JsCursor
}, JsCursor._
def jsonCollection: JSONCollection = ???
type ResultType = JsObject // any type which is provided a `Writes[T]`
jsonCollection.find(Json.obj()).cursor[ResultType].jsArray()
Run a raw command
The command API can be used with the JSON serialization to execution a JSON object as a raw command.
import scala.concurrent.{ ExecutionContext, Future }
import play.api.libs.json.{ JsObject, Json }
import reactivemongo.play.json._
import reactivemongo.api.commands.Command
def rawResult(db: reactivemongo.api.DefaultDB)(implicit ec: ExecutionContext): Future[JsObject] = {
val commandDoc = Json.obj(
"aggregate" -> "orders", // we aggregate on collection `orders`
"pipeline" -> List(
Json.obj("$match" -> Json.obj("status" -> "A")),
Json.obj(
"$group" -> Json.obj(
"_id" -> "$cust_id",
"total" -> Json.obj("$sum" -> "$amount"))),
Json.obj("$sort" -> Json.obj("total" -> -1))
)
)
val runner = Command.run(JSONSerializationPack)
runner.apply(db, runner.rawCommand(commandDoc)).one[JsObject]
}