Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to customize SpringWebFlux WebClient JSON deserialization?

I'm using a spring-webflux WebClient (build 20170502.221452-172) to access a Web application producing a stream of Entry objects (application/stream+json) like this:

final WebClient producerClient = WebClient.create("http://localhost:8080/");  Flux<Entry> entries = producerClient.get().uri("json-stream")         .accept(MediaType.APPLICATION_STREAM_JSON)         .exchange()         .flatMapMany(clientResponse -> clientResponse.bodyToFlux(Entry.class)); 

While the deserialization of the Entry objects works fine for POJOs using standard common types including Java time (JSR-310) datatypes like java.time.Instant, I wonder what I would have to do in order to add any custom JSON to Java deserialization (e. g., a custom Jackson ObjectMapper).

I can't find any API in WebClient or in the classes of the objects produced by its builder and fluent APIs to do that.

Has anybody used WebClient with customized deserialization?

(Maybe the API is not there, yet?)

like image 521
Martin Avatar asked May 03 '17 20:05

Martin


People also ask

How do I pass a JSON object in WebClient?

WebClient client = WebClient. of(); // Send a serialized JSON object with "applicaiton/json" HttpResponse response = client. postJson("/items", new MyItem()); HttpResponse response = client. putJson("/items", new MyItem()); HttpResponse response = client.

How do I get JSON response from WebClient?

You would just use bodyToMono which would return a Mono object. WebClient webClient = WebClient. create(); String responseJson = webClient. get() .

Does WebClient use Netty?

WebClient is a reactive and non-blocking interface for HTTP requests, based on Spring WebFlux. It has a functional, fluent API with reactive types for declarative composition. Behind the scenes, WebClient calls an HTTP client. Reactor Netty is the default and reactive HttpClient of Jetty is also supported.

Should ObjectMapper be a bean?

Assuming no configuration is required, just a plain ObjectMapper will do. It's OK to be declared as static. But in environment like Spring, IMHO you should declare it as a bean. Spring will manage its lifecycle for you.


1 Answers

Here's an example that customizes the ObjectMapper for JSON (de)serialization. Note that for streaming purposes, different encoders/decoders are being used but the principle remains the same for their configuration.

    ExchangeStrategies strategies = ExchangeStrategies             .builder()             .codecs(clientDefaultCodecsConfigurer -> {                 clientDefaultCodecsConfigurer.defaultCodecs().jackson2JsonEncoder(new Jackson2JsonEncoder(new ObjectMapper(), MediaType.APPLICATION_JSON));                 clientDefaultCodecsConfigurer.defaultCodecs().jackson2JsonDecoder(new Jackson2JsonDecoder(new ObjectMapper(), MediaType.APPLICATION_JSON));              }).build();      WebClient webClient = WebClient.builder().exchangeStrategies(strategies).build(); 
like image 123
Brian Clozel Avatar answered Sep 19 '22 14:09

Brian Clozel