Spring WebClient:解析+流式处理非常大的JSON

时间:2019-01-11 14:19:03

标签: spring-webflux

这个问题类似于Spring reactive streaming data from regular WebClient request,不同之处在于我不是立即从WebClient中获取JSON数组,而是类似这样的东西:

{
"result-set":{
"docs":[
  {"id":"auhcsasb1005_100000"},
  {"id":"auhcsasb1005_1000000"},
  {"id":"auhcsasb1005_1000001"},
  {"id":"auhcsasb1005_1000002"},
  .
  .
  .
  {EOF:true}
]
}

此JSON对象可能很大(〜100MB),因此需要进行处理并将其流式传输到客户端,而不是进行解析。这是我似乎能够正确获得语义的唯一方法:

WebClient.create()
  .get()
  .retrieve()
  .bodyToMono(DontKnowWhatClass.class)
  .flatMapMany(resultSet -> Flux.fromIterable(resultSet.getDocs()))

但是,这意味着我要在内存中反序列化100MB或更多,然后从中创建流量。我想知道的是:我是否缺少一些重要的东西?我能以某种方式从这样的对象创建助焊剂吗?不幸的是,我现在有办法影响结果集对象的呈现方式。

1 个答案:

答案 0 :(得分:0)

您可以接受一个 ServerWebExchange 到您的控制器,它有一个方法可以接受一个发布者 exchange.response.writeWith()

如果你有办法以块的形式解析有效载荷,你只需创建一个发射部分的 Flux。

例如,如果您根本不关心有效载荷而只想按原样发送:

    @GetMapping("/api/foo/{myId}")
    fun foo(exchange: ServerWebExchange, @PathVariable myId: Long): Mono<Void> {
        val content: Flux<DataBuffer> = webClient
            .get()
            .uri("/api/up-stream/bar/$myId")
            .exchange()
            .flatMapMany { it.bodyToFlux<DataBuffer>() }

        return exchange.response.writeWith(content)
    }

请务必检查内容协商设置,以避免出现意外缓冲。