知識庫 / REST RSS 訂閱

Java HttpClient – 將 JSON 響應映射到 Java 類

Jackson,REST
HongKong
10
09:47 PM · Dec 05 ,2025

1. 概述

我們知道,HttpClient 類,自 Java 11 引入以來,用於從服務器請求 HTTP 資源。它支持同步和異步編程模式。

在本教程中,我們將探索如何將 HTTP 響應映射到 Plain Old Java Object (POJO) 類中的不同方法。

2. 示例設置

讓我們編寫一個簡單的程序,Todo。該程序將消費一個假 REST API。我們將執行一個 GET 請求,並在稍後操作響應。

2.1. Maven 依賴

我們將使用 Maven 管理我們的依賴項。讓我們將 GsonJackson 依賴添加到我們的 pom.xml 中,以便在我們的程序中使用這些庫:

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.10.1</version>
</dependency>
        
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.16.0</version>
</dependency>

2.2. 示例項目

在本教程中,我們將使用一個虛假的 REST API 進行快速原型設計。

首先,讓我們查看在發出 GET 請求時,示例 API 的響應:

[
  {
    "userId": 1,
    "id": 1,
    "title": "delectus aut autem",
    "completed": false
  },
]

樣本API返回一個包含四個屬性的JSON響應。JSON響應包含多個對象,但為了簡化,我們跳過了它們。

接下來,我們創建一個POJO類用於數據綁定。類字段與JSON數據屬性相匹配。我們將包含構造函數、getter、setter、equals()toString()

public class Todo {
 
    int userId;
    int id;
    String title;
    boolean completed;
    
    // Standard constructors, getters, setters, equals(), and toString()
}

然後,讓我們創建一個名為 TodoAppClient</em/> 的類,其中包含我們的邏輯:

public class TodoAppClient { 
    
    ObjectMapper objectMapper = new ObjectMapper();
    Gson gson = new GsonBuilder.create();      
    
    // ...
}

我們還創建了新的 ObjectMapperGsonBuilder 實例。 這使得它對任何方法都可訪問且可重用。 在方法內部創建 ObjectMapper 實例可能是一種昂貴的操作。

最後,我們將編寫一個方法,該方法在樣本 API 上同步執行 GET 請求:

public class TodoAppClient { 

    // ...   

    String sampleApiRequest() throws Exception {
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
          .uri(URI.create("https://jsonplaceholder.typicode.com/todos"))
          .build();
 
        HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
 
        return response.body();
    }

    // ...
}

ofString() 方法來自 BodyHandlers,用於將響應體字節轉換為 String。 響應是一個 JSON String,方便在程序中進行操作。 在後續章節中,我們將探討如何將響應映射到 POJO 類。

讓我們為sampleApiRequest() 方法編寫一個單元測試:

@Test
public void givenSampleRestApi_whenApiIsConsumedByHttpClient_thenCompareJsonString() throws Exception {
    TodoAppClient sampleApi = new TodoAppClient();
    assertNotNull(sampleApi.sampleApiRequest());
}

測試確認API調用響應結果不為null

3. 使用 Jackson 將響應映射到 POJO 類

Jackson 是一個流行的 Java JSON 庫它有助於將 JSON 序列化和反序列化,以便進行進一步的操縱。 我們將使用它來反序列化示例設置中的 JSON 響應。 我們將把響應映射到 Todo POJO 類。

讓我們增強包含我們客户端邏輯的類。 我們將創建一個新方法並調用 sampleApiRequest() 方法以使響應可供映射:

public Todo syncJackson() throws Exception {
    
    String response = sampleApiRequest();  
    Todo[] todo = objectMapper.readValue(response, Todo[].class); 
    
    return todo[0];
 }

接下來,我們聲明瞭一個名為 Todo 的數組。最後,我們調用了 ObjectMapper 中的 readValue() 方法,將 JSON 字符串映射到 POJO 類。

讓我們通過將返回的 Todo 與一個預期的 Todo 實例進行比較來測試該方法:

@Test
public void givenSampleApiCall_whenResponseIsMappedByJackson_thenCompareMappedResponseByJackson() throws Exception {
    Todo expectedResult = new Todo(1, 1, "delectus aut autem", false); 
    TodoAppClient jacksonTest = new TodoAppClient();
    assertEquals(expectedResult, jacksonTest.syncJackson());
}

測試將預期結果與映射的 JSON 進行比較。它確認兩者相等。

4. 使用 Gson 將響應映射到 POJO 類

Gson 是 Google 開發的 Java 庫。它在 Java 生態系統中非常流行,與 Jackson 同樣受歡迎。它能夠幫助將 JSON 字符串映射到 Java 對象,以便進行進一步的處理。該庫還可以將 Java 對象轉換為 JSON。

我們將使用它將示例設置中的 JSON 響應映射到其對應的 POJO 類 Todo。讓我們在包含我們邏輯的類中編寫一個新的方法 syncGson()。

我們將調用 sampleApi() 以使 JSON 字符串可用,以便進行反序列化。

public Todo syncGson() throws Exception {
    String response = sampleApiRequest();
    List<Todo> todo = gson.fromJson(response, new TypeToken<List<Todo>>(){}.getType());
    return todo.get(0);
}

首先,我們創建了一個 Todo 類型列表。然後我們調用了 fromJson() 方法,將 JSON String 映射到 POJO 類。

JSON String 現在已映射到 POJO 類,以便進行進一步的操縱和處理。

讓我們為 syncGson() 編寫一個單元測試,通過將預期結果與返回的 Todo 進行比較:

@Test
public void givenSampleApiCall_whenResponseIsMappedByGson_thenCompareMappedGsonJsonResponse() throws Exception {
    Todo expectedResult = new Todo(1, 1, "delectus aut autem", false);   
    TodoAppClient gsonTest = new TodoAppClient();
    assertEquals(expectedResult, gsonTest.syncGson()); 
}

測試結果表明,預期結果與返回值相匹配。

5. 異步調用

現在,讓我們實現異步 API 調用。在異步模式中,線程不會等待其他線程完成。這種編程模式使數據獲取更健壯和可擴展。

讓我們異步地獲取樣板 API 並將 JSON 響應映射到 POJO 類。

5.1. 使用 Jackson 進行異步調用和映射到 POJO 類

在本教程中,我們使用兩個 Java 庫來反序列化 JSON 響應。讓我們使用 Jackson 實現異步調用和映射到 POJO 類的功能。首先,讓我們在 TodoAppClient 中創建一個方法,readValueJackson()

該方法反序列化 JSON 響應並將其映射到 POJO 類:

List<Todo> readValueJackson(String content) {
    try {
        return objectMapper.readValue(content, new TypeReference<List<Todo>>(){});
    } catch (IOException ioe) {
        throw new CompletionException(ioe);
    }
}

然後,讓我們為我們的邏輯類添加一個新方法:

public Todo asyncJackson() throws Exception {
    HttpClient client = HttpClient.newHttpClient();
    HttpRequest request = HttpRequest.newBuilder()
      .uri(URI.create("https://jsonplaceholder.typicode.com/todos"))
      .build(); 
  
    TodoAppClient todoAppClient = new TodoAppClient();
    List<Todo> todo = HttpClient.newHttpClient()
      .sendAsync(request, BodyHandlers.ofString())
      .thenApply(HttpResponse::body)
      .thenApply(todoAppClient::readValueJackson)
      .get();
 
    return todo.get(0);
}

該方法發起異步 GET 請求,並通過調用 readValueJackson() 將 JSON String 映射到 POJO 類。

最後,我們編寫一個單元測試,以將反序列化的 JSON 響應與 Todo 實例進行比較。

@Test
public void givenSampleApiAsyncCall_whenResponseIsMappedByJackson_thenCompareMappedJacksonJsonResponse() throws Exception {
    Todo expectedResult = new Todo(1, 1, "delectus aut autem", false);  
    TodoAppClient sampleAsyncJackson = new TodoAppClient();
    assertEquals(expectedResult, sampleAsyncJackson.asyncJackson());
}

預期結果與映射的JSON響應相等。

5.2. 使用 Gson 進行異步調用和映射到 POJO 類

讓我們通過將異步 JSON 響應映射到 POJO 類來進一步增強程序。首先,讓我們創建一個方法,用於反序列化 TodoAppClient 中的 JSON String

List<Todo> readValueGson(String content) {
    return gson.fromJson(content, new TypeToken<List<Todo>>(){}.getType());
}

接下來,讓我們為包含程序邏輯的類添加一個新的方法:

public Todo asyncGson() throws Exception {
    HttpClient client = HttpClient.newHttpClient();
    HttpRequest request = HttpRequest.newBuilder()
      .uri(URI.create("https://jsonplaceholder.typicode.com/todos"))
      .build();
    TodoAppClient todoAppClient = new TodoAppClient();
    List<Todo> todo = HttpClient.newHttpClient()
      .sendAsync(request, BodyHandlers.ofString())
      .thenApply(HttpResponse::body)
      .thenApply(todoAppClient::readValueGson)
      .get();
  
    return todo.get(0);
}

該方法發起一個異步的 GET 請求,並將 JSON 響應映射到 POJO 類。最後,我們調用 readValueGson() 來執行將響應映射到 POJO 類的過程。

現在,我們來編寫一個單元測試。我們將比較預期的 Todo 實例與映射後的響應。

@Test
public void givenSampleApiAsyncCall_whenResponseIsMappedByGson_thenCompareMappedGsonResponse() throws Exception {
    Todo expectedResult = new Todo(1, 1, "delectus aut autem", false); 
    TodoAppClient sampleAsyncGson = new TodoAppClient();
    assertEquals(expectedResult, sampleAsyncGson.asyncGson());
}

測試結果顯示,預期結果與映射的JSON響應相匹配。

6. 結論

在本文中,我們學習了四種將 JSON 響應映射到 POJO 類的方法,當使用 HttpClient 時。此外,我們還深入研究了使用 HttpClient 的同步和異步編程模式。我們還使用 Jackson 和 Gson 庫來反序列化 JSON 響應並將 JSON String 映射到 POJO 類。

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

發佈 評論

Some HTML is okay.