我认为play-iteratees-extras必须帮助你。这个库允许通过 Enumerator/Iteratee 模式解析 Json,当然,不要等待接收所有数据。
例如,不要构建代表“无限”Json 数组的“无限”字节流。
import play.api.libs.iteratee.{Enumeratee, Enumerator, Iteratee}
var i = 0
var isFirstWas = false
val max = 10000
val stream = Enumerator("[".getBytes) andThen Enumerator.generateM {
Future {
i += 1
if (i < max) {
val json = Json.stringify(Json.obj(
"prop" -> Random.nextBoolean(),
"prop2" -> Random.nextBoolean(),
"prop3" -> Random.nextInt(),
"prop4" -> Random.alphanumeric.take(5).mkString("")
))
val string = if (isFirstWas) {
"," + json
} else {
isFirstWas = true
json
}
Some(Codec.utf_8.encode(string))
} else if (i == max) Some("]".getBytes) // <------ this is the last jsArray closing tag
else None
}
}
好的,这个值包含 10000 个(或更多)对象的 jsArray。让我们定义将包含我们数组中每个对象的数据的案例类。
case class Props(prop: Boolean, prop2: Boolean, prop3: Int, prop4: String)
现在编写解析器,它将解析每个项目
import play.extras.iteratees._
import JsonBodyParser._
import JsonIteratees._
import JsonEnumeratees._
val parser = jsArray(jsValues(jsSimpleObject)) ><> Enumeratee.map { json =>
for {
prop <- json.\("prop").asOpt[Boolean]
prop2 <- json.\("prop2").asOpt[Boolean]
prop3 <- json.\("prop3").asOpt[Int]
prop4 <- json.\("prop4").asOpt[String]
} yield Props(prop, prop2, prop3, prop4)
}
请参阅docjsArray
和. _ 构建结果生成器:jsValues
jsSimpleObject
val result = stream &> Encoding.decode() ><> parser
Encoding.decode()
来自 JsonIteratees 包的字节将解码为CharString
. result
value 具有类型Enumerator[Option[Item]]
,您可以将一些 iteratee 应用于此枚举器以开始解析过程。
总的来说,我不知道您如何接收字节(解决方案在很大程度上取决于此),但我认为这显示了您的问题的可能解决方案之一。