Как разобрать ответ Spring 5 WebClient неблокирующим способом? - PullRequest
0 голосов
/ 02 июня 2018

Я использую Spring WebFlux WebClient для извлечения данных из внешнего API, например:

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);
}

Это прекрасно работает и выдает ответ, подобный этому:

{
    "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
}

НоМеня интересует только свойство "temp" (main -> temp).Как я мог преобразовать ответ (используя, например, Джексона ObjectMapper), чтобы возвращать только "temp" значение реактивным / неблокирующим способом?

Я понимаю, что первое, что заменяется ".retrieve () "by" .exchange () "но я не могу понять, как заставить это работать.

PS: Это мой первый вопрос здесь.Пожалуйста, дайте мне знать, если я делаю что-то не так или вам нужна дополнительная информация.

Спасибо!

1 Ответ

0 голосов
/ 03 июня 2018

Вам необходимо создать тип, соответствующий ответу, отправленному сервером.Очень минимальный пример может быть таким:

@JsonIgnoreProperties(ignoreUnknown = true)
public class WeatherResponse {
    public MainWeatherData main;
}

, а класс MainWeatherData может быть:

@JsonIgnoreProperties(ignoreUnknown = true)
public class MainWeatherData {
    public String temp;
}

Наконец, вы можете использовать WeatherResponse в bodyToMono:

...
   .retrieve()
   .bodyToMono(WeatherResponse.class);

Аннотация @JsonIgnoreProperties(ignoreUnknown = true) указывает Джексону не выдавать никаких ошибок, если он обнаруживает какое-либо значение в строке JSON, которого нет в вашем POJO.

Вы можете получить доступ к объекту WeatherResponseс оператором map в цепочке:

getWeatherByCityName(cityName)
     .map(weatherResponse -> weatherResponse.main.temp)  
...