AsyncRestTemplate was deprecated in #19962 in favor of WebClient. However, WebClient does not seem to support all of the use cases that AsyncRestTemplate supports (and which RestTemplate does not support.)
Consider the following JSON:
where both arrays (
Solution with AsyncRestTemplate
With AsyncRestTemplate, this is easy: Call
update the sum, proceed to the next element. Since only one Object of type
Overall, performing this streaming processing of the JSON can probably be done in 25 lines of code using Jackson and AsyncRestTemplate.
The Problem with WebClient
With WebClient, this kind of processing seems to be practically impossible. Jackson appears to only support async parsing at the token level. Anything at a higher level (e.g. ObjectMapper) needs to have all tokens available in a blocking way to parse them.
Therefore, to implement the kind of streaming processing described above, I would have to manually keep track of the JSON tokens parsed and then plug them into an ObjectMapper all at once when I've detected the end of an array element. This is basically what Spring currently does to support streaming of top-level arrays:
However, even to support only this very limited streaming of top-level array elements, Spring had to re-implement about 200 lines of Jackson logic to keep track of the current depth in the token stream (
Since AsyncRestTemplate is deprecated, there no longer seems to be an encouraged and practical way in Spring 5 to do asynchronous streaming of JSON data. There are several ways to improve this situation:
What are your thoughts on the matter and do you have plans to address this problem in a future release?
PS: A similar problem exists on the server side. With web-mvc, an object returned from a REST endpoint would be streamed into the output stream via Jackson, keeping the memory requirements low. With webflux, a Mono<Object> returned from a REST endpoint will first be serialized into a String before it is written to the output stream.
Rossen Stoyanchev commented
Jackson2Decoder supports streaming from json arrays as well as streaming line-delimited JSON when "content-type:application/stream+json" with a wire format:
Both of which translate naturally to Flux<V>.
For something like your case we could allow decoding to
Are you in control of both client and server side? In other words do you care about both encoding and decoding, and likewise are you able to even consider alternative output on the wire?
One extra consideration on the encoding side. For streaming media types like "text/event+stream" and "application/stream+json" we write and flush on every element since elements (e.g. events) may have time gaps in between. Your case sounds more like streaming lots of data without loading it in memory, so explicit flushing might not be required still. We'd have to consider some extra options for this, such as passing hints to EncodingHttpMessageWriter that wraps the JacksonEncoder.