How to parse a Spring 5 WebClient response in a non-blocking way?
You need to create a type that corresponds to the response sent by the server. A very minimal example could be like this:
@JsonIgnoreProperties(ignoreUnknown = true)
public class WeatherResponse {
public MainWeatherData main;
}
and the MainWeatherData
class could be:
@JsonIgnoreProperties(ignoreUnknown = true)
public class MainWeatherData {
public String temp;
}
Finally, you could use WeatherResponse
in bodyToMono
:
...
.retrieve()
.bodyToMono(WeatherResponse.class);
The @JsonIgnoreProperties(ignoreUnknown = true)
annotation instructs Jackson to not give any errors if it encounters any value in JSON string that is not present in you POJO.
You can access the WeatherResponse
object with a chained map
operator:
getWeatherByCityName(cityName)
.map(weatherResponse -> weatherResponse.main.temp)
Michel Nagme
Updated on July 25, 2022Comments
-
Michel Nagme over 1 year
I'm using Spring WebFlux WebClient to retrieve data from an external API, like this:
public WeatherWebClient() { this.weatherWebClient = WebClient.create("http://api.openweathermap.org/data/2.5/weather"); } public Mono<String> getWeatherByCityName(String cityName) { return weatherWebClient .get() .uri(uriBuilder -> uriBuilder .queryParam("q", cityName) .queryParam("units", "metric") .queryParam("appid", API_KEY) .build()) .accept(MediaType.APPLICATION_JSON) .retrieve() .bodyToMono(String.class); }
This works fine and produces a response like this:
{ "coord":{ "lon":-47.06, "lat":-22.91 }, "weather":[ { "id":800, "main":"Clear", "description":"clear sky", "icon":"01d" } ], "base":"stations", "main":{ "temp":16, "pressure":1020, "humidity":67, "temp_min":16, "temp_max":16 }, "visibility":10000, "wind":{ "speed":1, "deg":90 }, "clouds":{ "all":0 }, "dt":1527937200, "sys":{ "type":1, "id":4521, "message":0.0038, "country":"BR", "sunrise":1527932532, "sunset":1527971422 }, "id":3467865, "name":"Campinas", "cod":200 }
But I'm only interested in the "temp" property (main -> temp). How could I transform the response (using Jackson's ObjectMapper, for example) to return only "temp" value in a reactive/non-blocking way?
I understand the first thing is replacing ".retrieve()" by ".exchange()" but I can't figure out how to make it work.
PS: This is my first question here. Please let me know if I'm doing something wrong or if you need more details.
Thanks!
-
Michel Nagme over 5 yearsThanks @MuratOzkan, it worked like a charm! I was also relived to see that Jackson is Spring WebFlux library of choice to do that and they have non-blocking JSON parsing since version 2.9.0: github.com/FasterXML/jackson-core/issues/57