用Akka Stream流媒体巨大的json

时间:2017-06-10 15:51:57

标签: json scala playframework stream akka

我有一个带有json slab的巨大http响应的问题,其中只有一部分是兴趣点。 我无法改变响应结构。 这是一个例子

{
  "searchString": "search",
  "redirectUrl": "",
  "0": {
    "numRecords": 123,
    "refinementViewModelCollector": {},
//    Lots of data here
    "results": [
      {
        "productCode": "123",
        "productShortDescription": "Desc",
        "brand": "Brand",
        "productReview": {
          "reviewScore": 0
        },
        "priceView": {
          "salePriceDisplayable": false,
        },
        "productImageUrl": "url",
        "alternateImageUrls": [
          "url1"
        ],
        "largeProductImageUrl": "url4",
        "videoUrl": ""
      },
      {
        "productCode": "124",
        "productShortDescription": "Desc",
        "brand": "Brand",
        "productReview": {
          "reviewScore": 0
         },
        "priceView": {
          "salePriceDisplayable": false,
        },
        "preOrder": false,
        "productImageUrl": "url",
        "alternateImageUrls": [
          "url1"
        ],
        "largeProductImageUrl": "url4",
        "videoUrl": ""
      }
    ]
    //lots of data here
  }
}

我感兴趣的是results Jason Array中的条目,但它们位于json的中间

我创建了一个像这样的小型Play WS客户端:

val wsClient: WSClient = ???
val ret = wsClient.url("url").stream()
ret.flatMap { response =>
  response.body.via(JsonFraming.objectScanner(1024))
    .map(_.utf8String)
    .runWith(Sink.foreach(println))
}

这不起作用,因为它将整个json slab作为Json对象。我需要跳过一些数据,直到"results":条目出现在流中,然后开始解析条目并跳过所有其余的条目。 任何想法如何做到这一点?

3 个答案:

答案 0 :(得分:1)

有一些解析器支持解析为流。有关示例,请查看此Circe示例https://github.com/circe/circe/tree/master/examples/sf-city-lots

答案 1 :(得分:1)

签出Alpakka's JSON module,它可以传输嵌套JSON结构的特定部分:

response
  .body
  .via(JsonReader.select("$.0.results[*]"))
  .map(_.utf8String)
  .runWith(Sink.foreach(println)) // or runForeach(println)

答案 2 :(得分:0)

我希望对这个问题有一个更好的,针对Scala的答案,但是请查看Google GSON库文档中的“混合阅读示例”:

https://sites.google.com/site/gson/streaming

Gson还支持混合流和对象模型访问。这使您的应用程序具有两全其美的优势:对象模型访问的生产力和流式传输的效率 ... 此代码读取包含消息数组的JSON文档。它以流的形式逐步遍历数组元素,以避免将整个文档加载到内存中。简洁明了,因为它使用Gson的对象模型来解析单个消息

这应该具有出色的内存性能(代码从Java InputStream读取,因此完整的结构永远不会在内存中),但是可能需要一些努力才能将结果放入Scala案例类。