1. 背景
Jackson 是一個流行的 Java 庫,用於將 Java 對象序列化為 JSON,以及反向序列化 JSON 為 Java 對象。在某些情況下,Java 對象可能被定義為具有泛型類型。
在本教程中,我們將演示如何使用 Jackson 將 JSON 字符串反序列化為泛型類型。
2. 模型準備
對於要進行反序列化的給定的 JSON 字符串:
{"result":{"id":1,"firstName":"John","lastName":"Lewis"}}我們需要定義一個類,該類具有泛型類型參數和一個常規的POJO對象來存儲數據:
public class JsonResponse<T> {
private T result;
// getters and setters...
}public class User {
private Long id;
private String firstName;
private String lastName;
// getters and setters...
}3. 解序列化泛型類型
在 Jackson 中,<em>ObjectMapper</em> 提供了三個用於 JSON 解序列化的 <em>readValue</em> 方法集合,它們接受:
- Class<T> 作為參數,用於傳遞信息類型
- TypeReference 用於傳遞類型信息
- JavaType 作為參數
我們不能使用 <em>JsonResponse<User>.class</em> 傳遞到第一個 bullet point 中的方法,讓我們看看如何使用 <em>TypeReference</em> 和 <em>JavaType</em> 進行泛型解序列化。
3.1. <em >TypeReference</em>
如我們所知,Java 在編譯時會擦除泛型類型信息,但我們可以利用匿名內部類強大的功能,在編譯期間保留類型信息。Jackson 提供了抽象類 <em >TypeReference</em>,用於從派生子類獲取類型信息:
public abstract class TypeReference<T> {
protected final Type _type;
protected TypeReference() {
Type superClass = this.getClass().getGenericSuperclass();
this._type = ((ParameterizedType)superClass).getActualTypeArguments()[0];
}
}使用 TypeReference,我們可以為泛型類型 JsonResponse<User> 創建一個匿名內部類,如下所示:
TypeReference<JsonResponse<User>> typeRef = new TypeReference<JsonResponse<User>>() {};這種用於保留泛型類型信息的方案被稱為超類型標記(super type token)。通過使用超類型標記,Jackson 將知道容器類型是 JsonResponse ,其類型參數是 User 。
以下是反序列化的完整測試用例:
@Test
void givenJsonObject_whenDeserializeIntoGenericTypeByTypeReference_thenCorrect() throws JsonProcessingException {
String json = "{\"result\":{\"id\":1,\"firstName\":\"John\",\"lastName\":\"Lewis\"}}";
TypeReference<JsonResponse<User>> typeRef = new TypeReference<JsonResponse<User>>() {};
JsonResponse<User> jsonResponse = objectMapper.readValue(json, typeRef);
User user = jsonResponse.getResult();
assertThat(user.getId()).isEqualTo(1);
assertThat(user.getFirstName()).isEqualTo("John");
assertThat(user.getLastName()).isEqualTo("Lewis");
}3.2. <em >JavaType</em>
如果類型參數 <em >T</em> 不是靜態的,則需要使用 <em >JavaType</em> 而不是 <em >TypeReference</em> 來傳遞解序列化所需的類型信息。<em >ObjectMapper</em> 提供了這樣的方法,並且從 Jackson 2.5 版本開始,現在推薦使用它們。我們可以使用 <em >TypeFactory</em> 來構造包含我們類型參數的 <em >JavaType</em> 對象:
JavaType javaType = objectMapper.getTypeFactory().constructParametricType(JsonResponse.class, User.class);
JsonResponse<User> jsonResponse = objectMapper.readValue(json, javaType);這裏 作為第二個參數傳遞給 方法,可以輕鬆地更改為其他參數化類型。
4. 結論
在本文中,我們介紹了兩種將 JSON 字符串反序列化為具有泛型類型的對象的簡單方法。