1. 概述
Java 11引入的HttpClient
类,是处理HTTP请求的利器。它支持同步和异步两种编程模式,让开发者能灵活处理网络通信。
本文将深入探讨如何将HttpClient
获取的JSON响应数据映射为POJO(Plain Old Java Object)对象,这是实际开发中的高频需求。
2. 示例项目搭建
我们通过一个Todo
示例程序来演示,该程序会调用一个模拟REST API,执行GET请求并处理响应数据。
2.1 Maven依赖
使用Maven管理依赖,在pom.xml
中添加Gson和Jackson库:
<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 项目结构
我们使用JSONPlaceholder提供的模拟API进行快速原型开发。
API响应示例:
[
{
"userId": 1,
"id": 1,
"title": "delectus aut autem",
"completed": false
},
]
响应包含四个属性,为简化演示,我们只处理单个对象。
创建POJO类:
public class Todo {
int userId;
int id;
String title;
boolean completed;
// 标准构造器、getter/setter、equals()和toString()
}
创建客户端类:
public class TodoAppClient {
ObjectMapper objectMapper = new ObjectMapper();
Gson gson = new GsonBuilder().create();
// ...
}
⚠️ 性能提示:ObjectMapper
和Gson
实例应复用,避免在方法内频繁创建。
同步请求方法:
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();
}
// ...
}
BodyHandlers.ofString()
将响应体转换为String格式,便于后续处理。
单元测试:
@Test
public void givenSampleRestApi_whenApiIsConsumedByHttpClient_thenCompareJsonString() throws Exception {
TodoAppClient sampleApi = new TodoAppClient();
assertNotNull(sampleApi.sampleApiRequest());
}
3. 使用Jackson映射响应
Jackson是Java生态中最流行的JSON处理库,提供强大的序列化和反序列化能力。
映射方法实现:
public Todo syncJackson() throws Exception {
String response = sampleApiRequest();
Todo[] todo = objectMapper.readValue(response, Todo[].class);
return todo[0];
}
关键步骤:
- 获取JSON字符串
- 使用
readValue()
映射为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());
}
✅ 验证映射结果与预期对象一致。
4. 使用Gson映射响应
Gson是Google出品的JSON库,与Jackson并驾齐驱,同样提供JSON与Java对象的转换能力。
映射方法实现:
public Todo syncGson() throws Exception {
String response = sampleApiRequest();
List<Todo> todo = gson.fromJson(response, new TypeToken<List<Todo>>(){}.getType());
return todo.get(0);
}
核心操作:
- 获取JSON字符串
- 使用
fromJson()
配合TypeToken
处理泛型 - 返回列表首元素
单元测试:
@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. 异步调用处理
异步编程能显著提升系统吞吐量,HttpClient
原生支持异步模式。
5.1 Jackson异步映射
反序列化方法:
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);
}
执行流程:
- 发送异步请求
- 获取响应体
- 调用反序列化方法
- 阻塞获取结果
单元测试:
@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());
}
5.2 Gson异步映射
反序列化方法:
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);
}
单元测试:
@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());
}
6. 总结
本文系统介绍了四种将JSON响应映射为Java对象的方法:
场景 | 同步方案 | 异步方案 |
---|---|---|
Jackson | ✅ 已实现 | ✅ 已实现 |
Gson | ✅ 已实现 | ✅ 已实现 |
关键要点:
HttpClient
是Java 11+处理HTTP请求的标准工具- Jackson和Gson都能高效完成JSON映射
- 异步模式适合高并发场景
- 复用
ObjectMapper
/Gson
实例可提升性能
完整示例代码可在GitHub获取。实际开发中,建议根据项目需求选择合适的库和调用模式。