我已经动态计算了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有效,但我认为这不是正确的做法。 有更清洁的解决方案吗?