Отправьте JsArray, используя кодировку передачи Chunked.
У меня есть динамически вычисленная коллекция jsObject.
val collection: Enumerator[JsObject] = ???
Я хочу преобразовать свою коллекцию в JsArray и отправить JsArray, используя кодировку передачи по частям.
import play.api.libs.iteratee.{Iteratee, Enumerator}
import play.api.libs.json._
import play.api.mvc.{Action, Controller}
import scala.concurrent.{Future, ExecutionContext}
import scala.concurrent.ExecutionContext.Implicits.global
def f(i: Int): JsObject = JsObject(Seq("foo" -> JsNumber(i)))
val collection: Enumerator[JsObject] =
Enumerator.enumerate(List(1,2,3).map(f))
/**
* Creates a JSON array from a key value iteratee
*/
def jsonArrayCreator(implicit ctx: ExecutionContext): Iteratee[JsObject, JsArray] =
Iteratee.getChunks.map(values => new JsArray(values))
def toJsArray(e: Enumerator[JsObject]): Enumerator[String] = {
var i = 0
def _counter = { i += 1; i }
Enumerator("[") >>> e.map {
x => if (_counter == 1) Json.stringify(x) else s",${Json.stringify(x)}"
} >>> Enumerator("]")
}
object Bar extends Controller {
// solution 1
def getChunked = Action {
Ok.chunked(collection)
// res: {"foo":1}{"foo":2}{"foo":3}
}
// solution 2
def getJsArray = Action.async {
val fJsArray: Future[JsArray] = collection |>>> jsonArrayCreator
fJsArray.map(Ok(_))
// res: [{"foo":1},{"foo":2},{"foo":3}]
}
// solution 3
def getJsArrayChunked = Action {
Ok.chunked(toJsArray(collection))
.withHeaders("Content-type" -> "application/json)")
//res: [{"foo":1},{"foo":2},{"foo":3}]
}
}
Решение 1 недействительно, так как результат не является действительным Json.
Решение 2 не использует кодирование передачи по частям.
Решение 3 работает, но я не думаю, что это правильный способ делать то, что я хочу. Есть ли более чистое решение?