使用Chunked传输编码发送JsArray

时间:2015-09-22 11:20:25

标签: scala playframework chunked-encoding iterate

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

0 个答案:

没有答案