知識庫 / HTTP Client-Side RSS 訂閱

使用 Spring RestTemplate 獲取 JSON 對象列表

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

1. 概述

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

在 Spring 中,我們可以使用 <em >RestTemplate</em> 來執行同步的 HTTP 請求。數據通常以 JSON 格式返回,<em >RestTemplate</em> 可以自動將其轉換為我們需要的格式。

在本教程中,我們將探索如何將 JSON 數組轉換為 Java 中三種不同的對象結構:Array 中的 ObjectArray 中的 POJO 以及 List 中的 POJO。

2. JSON, POJO 和服務

假設我們有一個端點 http://localhost:8080/users 返回以下 JSON 格式的用户列表:

[{
  "id": 1,
  "name": "user1",
}, {
  "id": 2,
  "name": "user2"
}]

我們將會需要相應的 用户 類來處理數據:

public class User {
    private int id;
    private String name;

    // getters and setters..
}

對於我們的接口實現,我們編寫一個 UserConsumerServiceImpl,其中 RestTemplate 作為其依賴項:

public class UserConsumerServiceImpl implements UserConsumerService {

    private final RestTemplate restTemplate;

    public UserConsumerServiceImpl(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

...
}

3. 將 JSON 對象列表映射

當 REST 請求的響應是一個 JSON 數組時,有幾種方法可以將它轉換為 Java 集合。

讓我們看看這些選項以及它們如何輕鬆地處理返回的數據。我們將查看從 REST 服務返回的某些用户對象中提取用户名。

3.1. 使用 Object 數組的 RestTemplate

首先,我們使用 RestTemplate.getForEntity 方法並使用 ResponseEntity 類型為 Object[] 以收集響應:

ResponseEntity<Object[]> responseEntity =
   restTemplate.getForEntity(BASE_URL, Object[].class);

接下來,我們可以將正文提取到我們的 Object 數組中:

Object[] objects = responseEntity.getBody();

這裏實際的 對象 只是包含我們數據的任意結構,但沒有使用我們的 用户 類型。讓我們將其轉換為我們的 用户 對象。

為此,我們需要一個 對象映射器

ObjectMapper mapper = new ObjectMapper();

我們可以將其聲明為內聯,儘管這通常作為類的一個私有靜態常量成員來完成。

最後,我們準備提取用户名:

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

使用這種方法,我們可以將任意類型的數據有效地轉換為 Java 中的 數組對象。這在僅需要計數結果時非常方便。

然而,它並不適合進一步的處理。我們需要付出額外的努力將其轉換為我們能夠處理的類型。

Jackson 解序列化器實際上會將 JSON 序列化為一系列 LinkedHashMap 對象,當我們要求它將目標類型設置為 Object 時。使用 convertValue 進行後處理是一種低效的開銷。

如果我們直接向 Jackson 提供所需的類型,就可以避免這種情況。

3.2. 使用 User 數組的 RestTemplate

我們可以將 User[] 提供給 RestTemplate,而不是 Object[]

  ResponseEntity<User[]> responseEntity = 
    restTemplate.getForEntity(BASE_URL, User[].class); 
  User[] userArray = responseEntity.getBody();
  return Arrays.stream(userArray) 
    .map(User::getName) 
    .collect(Collectors.toList());

我們能看出,我們不再需要 ObjectMapper.convertValueResponseEntity 內部已經包含 User 對象。 但為了使用 Java 的 Stream API 以及為了使我們的代碼能夠與 List 配合工作,我們仍然需要進行一些額外的轉換。

3.3. 使用 User 列表和 ParameterizedTypeReference

如果我們需要 Jackson 產生一個 List 中的 User 對象,而不是數組,則需要描述我們想要創建的 List。為此,我們需要使用 RestTemplateexchange 方法。

該方法接受由匿名內部類產生的 ParameterizedTypeReference

ResponseEntity<List<User>> responseEntity = 
  restTemplate.exchange(
    BASE_URL,
    HttpMethod.GET,
    null,
    new ParameterizedTypeReference<List<User>>() {}
  );
List<User> users = responseEntity.getBody();
return users.stream()
  .map(User::getName)
  .collect(Collectors.toList());

這會產生我們想要使用的列表

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

在第一個和第二個示例中,Spring 可以輕鬆地將 JSON 解析為User.class類型令牌,其中運行時可以完全獲取類型信息。

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

我們可以通過使用一個父類型令牌參數化類型引用來克服這個問題。實例化它為匿名內部類——new ParameterizedTypeReference<List<User>>() {}——利用了泛型類子類的編譯時類型信息不受類型擦除的影響,並且可以通過反射來消費這些信息。

4. 結論

在本文中,我們探討了三種使用 RestTemplate 處理 JSON 對象的方法。我們瞭解瞭如何指定 Object 數組的類型以及自定義類的類型。

然後,我們學習瞭如何通過使用 ParameterizedTypeReference 提供類型信息,從而生成 List

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

發佈 評論

Some HTML is okay.