知識庫 / HTTP Client-Side RSS 訂閱

使用 WebClient 獲取 JSON 對象列表

HTTP Client-Side,JSON,Spring Web
HongKong
11
09:51 PM · Dec 05 ,2025

1. 概述

我們的服務經常與其他的 REST 服務進行通信,以獲取信息。

從 Spring 5 開始,我們可以使用 <em >WebClient</em> 來執行這些請求,以一種反應式、非阻塞的方式。<em >WebClient</em> 是新 <em >WebFlux</em> 框架的一部分,該框架建立在 <em >Project Reactor</em> 之上。它具有流式、反應式的 API,並且在底層實現中使用了 HTTP 協議。

當我們發起一個 Web 請求時,數據通常以 JSON 格式返回。<em >WebClient</em> 可以代表我們進行轉換。

在本文中,我們將瞭解如何使用 <em >WebClient</em> 將 JSON 數組轉換為 Java 中的 <em >Array</em> (對象數組)、POJO 數組以及 POJO 列表。

2. 依賴項

要使用 WebClient,我們需要將幾個依賴項添加到我們的 pom.xml 中:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
    <groupId>org.projectreactor</groupId>
    <artifactId>reactor-spring</artifactId>
    <version>1.0.1.RELEASE</version>
</dependency>

3. JSON、POJO 和服務

讓我們從一個端點 http://localhost:8080/readers 開始,它返回一個包含讀者及其最喜歡的書籍的 JSON 數組:

[{
    "id": 1,
    "name": "reader1",
    "favouriteBook": { 
        "author": "Milan Kundera",
        "title": "The Unbearable Lightness of Being"
    }
}, {
    "id": 2,
    "name": "reader2"
    "favouriteBook": { 
        "author": "Douglas Adams",
        "title": "The Hitchhiker's Guide to the Galaxy"
    }
}]

我們需要相應的 Reader Book 類來處理數據:

public class Reader {
    private int id;
    private String name;
    private Book favouriteBook;

    // getters and setters..
}
public class Book {
    private final String author;
    private final String title;

   // getters and setters..
}

對於我們的接口實現,我們使用 ReaderConsumerServiceImpl ,並使用 WebClient 作為其依賴項:

public class ReaderConsumerServiceImpl implements ReaderConsumerService {

    private final WebClient webClient;

    public ReaderConsumerServiceImpl(WebClient webclient) {
        this.webclient = webclient;
    }

    // ...
}

4. 將 JSON 對象列表映射到 Java 集合

當從 REST 請求接收 JSON 數組時,有多種方法將其轉換為 Java 集合。讓我們探討各種選項,並瞭解如何輕鬆處理返回的數據。我們將分析讀者最喜歡的書籍。

4.1. Mono vs. Flux

Project Reactor 引入了兩個Publisher 實現:MonoFlux

Flux<T> 在我們需要處理零個到多個,或者潛在無限的結果時非常有用。我們可以將一個 Twitter 動態源(動態源)作為例子。

當我們知道結果一次性返回——就像我們的用例一樣——我們可以使用 Mono<T>.

4.2. 使用 WebClientObject 數組

首先,使用 WebClientget 方法進行調用,並使用類型為 Object[]Mono 來收集響應:

Mono<Object[]> response = webClient.get()
  .accept(MediaType.APPLICATION_JSON)
  .retrieve()
  .bodyToMono(Object[].class).log();

接下來,我們把內容提取到我們的 Object 數組中:

Object[] objects = response.block();

實際的 對象 指的是一個任意結構,包含我們的數據。讓我們將其轉換為 Reader 對象數組。

為此,我們需要一個 ObjectMapper

ObjectMapper mapper = new ObjectMapper();

在這裏,我們將其聲明為內聯,儘管通常將其作為類的私有靜態常量成員進行聲明。

最後,我們準備提取讀者的最愛書籍並將其收集到一個列表中:

return Arrays.stream(objects)
  .map(object -> mapper.convertValue(object, Reader.class))
  .map(Reader::getFavouriteBook)
  .collect(Collectors.toList());

當我們要求 Jackson 解序列化器產生 Object 作為目標類型時,它實際上會將 LinkedHashMap 對象序列化成一系列 JSON 對象。 使用 convertValue 進行後處理效率低下。 如果我們在序列化過程中提供我們期望的類型給 Jackson,就可以避免這種情況。

4.3. 使用 Reader 數組與 WebClient

我們可以為我們的 WebClient 提供 Reader[] 數組,而不是 Object[] 數組。

Mono<Reader[]> response = webClient.get()
  .accept(MediaType.APPLICATION_JSON)
  .retrieve()
  .bodyToMono(Reader[].class).log();
Reader[] readers = response.block();
return Arrays.stream(readers)
  .map(Reader:getFavouriteBook)
  .collect(Collectors.toList());

在這裏,我們可以觀察到我們不再需要 ObjectMapper.convertValue。但是,我們仍然需要進行額外的轉換,以便使用 Java 的 Stream API 以及為了使我們的代碼與 List 兼容。

4.4. 使用 WebClientReader List

如果希望 Jackson 生成 ReaderList 而不是數組,我們需要描述我們想要創建的 List。為此,我們向方法提供一個由匿名內部類產生的 ParameterizedTypeReference

Mono<List<Reader>> response = webClient.get()
  .accept(MediaType.APPLICATION_JSON)
  .retrieve()
  .bodyToMono(new ParameterizedTypeReference<List<Reader>>() {});
List<Reader> readers = response.block();

return readers.stream()
  .map(Reader::getFavouriteBook)
  .collect(Collectors.toList());

這讓我們能夠使用 列表進行操作。

讓我們更深入地瞭解 為什麼我們需要使用 參數化類型引用

Spring的WebClient可以輕鬆地將JSON反序列化為 Reader.class,當運行時類型信息可用時。

然而,使用泛型時,如果嘗試使用 List<Reader>.class,則會發生泛型擦除。因此,Jackson將無法確定泛型的類型參數。

通過使用 參數化類型引用,我們可以解決這個問題。將其實例化為匿名內部類利用了泛型類子類的編譯時類型信息,這些信息不受類型擦除的影響,並且可以通過反射進行消費。

5. 結論

在本教程中,我們探討了三種使用 WebClient 的方式來處理 JSON 對象。我們還學習瞭如何指定數組的 Object 類型以及自定義類。

我們還學習瞭如何使用 ParameterizedTypeReference 來提供生成 List 的信息類型。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.