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

Jackson,REST
Remote
1
08:42 PM · Nov 30 ,2025

1. 概述

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

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

2. Example Setup

Let’s write a simple program, Todo. The program will consume a fake REST API. We’ll perform a GET request and later manipulate the response.

2.1. Maven Dependencies

We’ll manage our dependencies with Maven. Let’s add Gson and Jackson dependencies to our pom.xml to make the libraries available for use in our program:

<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. Sample Project

In this tutorial, we’ll use a fake REST API for fast prototyping.

First, let’s view the sample API response when the GET request is invoked:

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

The sample API returns a JSON response with four properties. The JSON response has more than one object, but we are skipping them for simplicity.

Next, let’s create a POJO class for data binding. The class field matches the JSON data properties. We’ll include constructors, getters, setters, equals()>, and toString():

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

Then, let’s create a class TodoAppClient that will contain our logic:

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

Also, we created new instances of ObjectMapper and GsonBuilder. This makes it accessible and reusable for any method. Creating instances of ObjectMapper inside a method could be an expensive operation.

Finally, we’ll write a method that performs GET requests synchronously on the sample API:

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

    // ...
}

The ofString() method from BodyHandlers helps convert the response body bytes to String. The response is a JSON String for easy manipulation in the program. In later sections, we’ll explore ways of mapping the response to the POJO class.

Let’s write a unit test for the sampleApiRequest() method:

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

The test ascertains that the response from the API call is not 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 數組。 最後,我們調用 readValue() ObjectMapper 以將 JSON String 映射到 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 String} 映射到 Java 對象,以便進行進一步處理。該庫還可以將 Java 對象轉換為 JSON。

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

我們將調用 sampleApi() 以使 JSON String} 可用作反序列化。

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

首先,我們創建了一個 Todo 類型的 List。然後我們調用了 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. Asynchronous Call

Now, let’s implement the API call asynchronously. In an asynchronous pattern, threads don’t wait for each other to complete. This programming pattern makes fetching data more robust and scalable.

Let’s fetch the sample API asynchronously and map the JSON response to the POJO class.

5.1. Asynchronous Call and Mapping to POJO Class Using Jackson

In this tutorial, we are using two Java libraries to deserialize the JSON response. Let’s implement asynchronous call mapping with Jackson. First, let’s create a method, readValueJackson(), in TodoAppClient.

The method deserializes the JSON response and maps it to the POJO class:

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

Then, let’s add a new method to our logic class:

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

The method makes asynchronous GET requests and maps the JSON String to the POJO class by invoking the readValueJackson().

Finally, let’s write a unit test to compare the deserialized JSON response with an expected instance of 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());
}

The expected result and the mapped JSON response are equal.

5.2. Asynchronous Call and Mapping to POJO Class Using Gson

Let’s further enhance the program by mapping asynchronous JSON responses to the POJO class. First, let’s create  a method to deserialize the JSON String in TodoAppClient:

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

Next, let’s add a new method to the class containing our program logic:

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

The method makes an asynchronous GET request and maps the JSON response to the POJO class. Finally, we invoked readValueGson() to perform the process of mapping the response to the POJO class.

Let’s write a unit test. We’ll compare the expected new instance of Todo with the mapped response:

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

The test shows that the expected result matched the mapped JSON response.

6. 結論

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

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

發佈 評論

Some HTML is okay.