使用 Jackson 將 JSON 集合反序列化為物件集合

假設你有一個 pojo 類 Person

public class Person {
    public String name;

    public Person(String name) {
        this.name = name;
    }
}

並且你希望將其解析為 JSON 陣列或 Person 物件的對映。由於型別擦除,你無法在執行時直接構造 List<Person>Map<String, Person> 的類 (因此使用它們來反序列化 JSON) 。為了克服這個限制,傑克遜提供了兩種方法 - TypeFactoryTypeReference

TypeFactory

這裡採用的方法是使用工廠(及其靜態實用程式功能)為你構建型別。它所使用的引數是你要使用的集合(列表,集等)以及要儲存在該集合中的類。

TypeReference

型別參考方法似乎更簡單,因為它可以節省你一些打字和看起來更乾淨。TypeReference 接受一個型別引數,你可以在其中傳遞所需的型別 List<Person>。你只需例項化此 TypeReference 物件並將其用作型別容器。

現在讓我們看看如何將 JSON 實際反序列化為 Java 物件。如果你的 JSON 格式化為陣列,則可以將其反序列化為 List。如果存在更復雜的巢狀結構,則需要反序列化為 Map。我們將看看兩者的例子。

反序列化 JSON 陣列

String jsonString = "[{\"name\": \"Alice\"}, {\"name\": \"Bob\"}]"

TypeFactory 方法

CollectionType listType = 
    factory.constructCollectionType(List.class, Person.class);
List<Preson> list = mapper.readValue(jsonString, listType);

TypeReference 方法

TypeReference<Person> listType = new TypeReference<List<Person>>() {};
List<Person> list = mapper.readValue(jsonString, listType);

反序列化 JSON 對映

String jsonString = "{\"0\": {\"name\": \"Alice\"}, \"1\": {\"name\": \"Bob\"}}"

TypeFactory 方法

CollectionType mapType = 
    factory.constructMapLikeType(Map.class, String.class, Person.class);
List<Person> list = mapper.readValue(jsonString, mapType);

TypeReference 方法

TypeReference<Person> mapType = new TypeReference<Map<String, Person>>() {};
Map<String, Person> list = mapper.readValue(jsonString, mapType);

細節

使用的匯入語句:

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.CollectionType;

使用的例項:

ObjectMapper mapper = new ObjectMapper();
TypeFactory factory = mapper.getTypeFactory();

注意

雖然 TypeReference 方法可能看起來更好,但它有幾個缺點:

  1. TypeReference 應該使用匿名類進行例項化
  2. 你應該提供通用的明確性

如果不這樣做可能會導致泛型型別引數的丟失,從而導致反序列化失敗。