Reputation: 3828
What is the fastest way to return JSON text from BSONArray?
I'm returning very big JSON document. Is it possible to omit processing Play
JsValue
Now I'm returning like this:
val result:BSONArray = ....
Ok(Json.toJson(result))
I think faster would be something like:
Ok(result.toTextJSON).as(MimeTypes.JSON)
Update here my full code:
val command = Json.parse( s""" {
"aggregate": "$collection",
"pipeline": [
{ "$$match": { "$$and" : [
{ "${RootAttrs.TIME}" : { "$$gt": $startSecTime }},
{ "${RootAttrs.TIME}" : { "$$lt": $endSecTime }},
{ "${RootAttrs.COMMAND}" : { "$$eq": ${toCmd(Command.GPS_COORDINATES)} }}
]
}},
{ "$$sort": { "${RootAttrs.TIME}" : 1 }},
{ "$$limit": $MAX_GPS_ALL_DATA },
{ "$$project" : { "_id":0, "${RootAttrs.TIME}":1, "${RootAttrs.COMMAND}":1, "${RootAttrs.VALUE}":1, "${RootAttrs.IGNITION}":1, "${RootAttrs.SIM_NUMBER}":1 } }
]}""")
db.command(RawCommand(BSONDocumentFormat.reads(command).get)).map { out =>
out.get("result").map {
case result: BSONArray =>
Logger.debug("Loaded all GPS history data size: " + result.length)
Ok(Json.toJson(result)) // <- I need just return JSON, parsing to JsValue can take some time
case _ =>
Logger.error("Result GPS history data not array")
BadRequest
}.getOrElse(BadRequest)
}
Upvotes: 0
Views: 118
Reputation: 6203
You can bypass the step of creating the intermediary JsValue if you want to create your own Writeable, and output the string more manually.
Here is a simple example which can be customised to your need
val result: BSONArray = BSONArray("one", "two", "three")
def convertBsonArrayToString(jsval: BSONArray): Array[Byte] = {
// this method assumes I have a BSONArray of Strings (which you may not)
var strs: Stream[String] = jsval.stream.map(_.get match { case s: BSONString => s.value })
var json: String = strs.mkString("[\"", "\",\"", "\"]")
json.getBytes()
}
implicit def writeableOf_BSONArray: Writeable[BSONArray] = {
Writeable(convertBsonArrayToString ,Some("application/json"))
}
def doStuff = action {
Results.Ok(result)
}
The response above is ["one","two","three"]
If you are dealing with massive data - you may also be better off using an Enumerator, and streaming the response.
see: https://www.playframework.com/documentation/2.5.x/ScalaStream
Upvotes: -1