首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Jackson 核心功能詳解:對象序列化、反序列化與泛型容器 TypeReference 實戰

     編輯:Java 相關知識

ObjectMapper 核心地位

ObjectMapper 是 Jackson 數據綁定的入口,線程安全,全應用單例。核心雙方法:

  • writeValue(dest, obj):序列化 → 文件、流、字符串、字節數組。
  • readValue(src, Type):反序列化 ← 文件、流、字符串、字節數組。

1. 基礎 POJO 序列化與反序列化


// POJO 必須有無參構造函數,字段提供 getter/setter 或公共字段
public class Student {
    private String name;
    private int age;
    // getter/setter/toString 省略
}

// 序列化
Student s = new Student("王五", 20);
mapper.writeValue(new File("student.json"), s);
// 文件內容: {"name":"王五","age":20}

// 反序列化
Student s2 = mapper.readValue(new File("student.json"), Student.class);

2. 泛型容器反序列化:TypeReference 關鍵作用

Java 類型擦除導致運行時丟失泛型信息,mapper.readValue(json, List.class) 只能得到 List。必須使用 TypeReference 匿名內部類保留類型簽名。


// 映射到 Map 結構
String json = "{\"userData1\":{\"student\":{\"name\":\"趙六\",\"age\":22},\"name\":\"趙六\",\"verified\":false,\"marks\":[80,90,95]}}";

TypeReference> typeRef = new TypeReference>() {};
Map map = mapper.readValue(json, typeRef);

UserData data = map.get("userData1");
System.out.println(data.getStudent().getName()); // 類型安全,無需強轉

UserData 定義


public class UserData {
    private Student student;
    private String name;
    private Boolean verified;
    private int[] marks;
    // getter/setter
}

3. 常見容器類型反序列化模板

JSON 結構TypeReference 寫法獲取方式
對象數組 [{"id":1},{"id":2}]new TypeReference>(){}List list = mapper.readValue(json, typeRef);
Map 值為對象 {"k1":{...}}new TypeReference>(){}Map map = ...
嵌套 List [[1,2],[3,4]]new TypeReference>>{}List> nested = ...
Map 值為 List {"k1":[1,2]}new TypeReference>>{}Map> map = ...

4. 日期、枚舉、可選字段處理


// 配置
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); // 忽略 null

// POJO
public class Order {
    private LocalDateTime createTime; // 需註冊 JavaTimeModule
    private Status status; // Enum
    private String remark; // 可為 null
}

// Java 8 時間支持需添加模塊
mapper.registerModule(new JavaTimeModule());

5. 流式 API 處理超大數據 (低內存)


// 序列化大 List 到文件,不全量進內存
try (JsonGenerator gen = mapper.getFactory().createGenerator(new File("huge.json"), JsonEncoding.UTF_8)) {
    gen.writeStartArray();
    for (Student s : hugeList) {
        mapper.writeValue(gen, s); // 逐個寫入
    }
    gen.writeEndArray();
}

// 反序列化大數組流式讀取
try (JsonParser parser = mapper.getFactory().createParser(new File("huge.json"))) {
    if (parser.nextToken() == JsonToken.START_ARRAY) {
        while (parser.nextToken() == JsonToken.START_OBJECT) {
            Student s = mapper.readValue(parser, Student.class);
            process(s); // 逐個處理,釋放內存
        }
    }
}

6. 性能優化清單

  1. Afterburner 模塊:mapper.registerModule(new AfterburnerModule()),字節碼生成替代反射,序列化/反序列化提速 20-30%。
  2. 單例複用:ObjectMapper 創建昂貴 (註解掃描、序列化器緩存),全局單例。
  3. 避免 writeValueAsString 大對象:直接 writeValue(OutputStream, obj) 避免中間巨大字符串。
  4. 關閉不需要的特性:FAIL_ON_UNKNOWN_PROPERTIES=false、WRITE_DATES_AS_TIMESTAMPS=false 等按需配置。

7. 常見異常與排查

異常原因解決
JsonMappingException: No suitable constructor無無參構造函數添加無參構造或 @JsonCreator
JsonMappingException: Infinite recursion雙向引用循環@JsonManagedReference/@JsonBackReference 或 @JsonIdentityInfo
UnrecognizedPropertyExceptionJSON 多餘字段配置 FAIL_ON_UNKNOWN_PROPERTIES=false 或 @JsonIgnoreProperties
InvalidDefinitionException: Cannot construct instance of Interface接口/抽象類無實現@JsonDeserialize(as=Impl.class) 或多態配置

總結

Jackson 以 ObjectMapper 為核心,TypeReference 解決泛型擦除是反序列化容器的關鍵。掌握 POJO 規範、日期/枚舉模塊、流式 API、Afterburner 加速及異常排查,即可高效、穩健地處理各類 JSON 數據綁定場景。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved