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

Jackson 實現 Java 對象與 JSON 高效互轉完整教程

     編輯:Java 相關知識

前言

Jackson 是 Java 生態中事實標準的 JSON 處理庫,核心類 ObjectMapper 提供了序列化、反序列化、樹模型、流式 API 三種範式。本文系統講解三種模式用法、泛型反序列化、日期/枚舉/空值處理、註解定制、效能優化與常見坑點。

一、核心入門:Data Binding(數據綁定)

1.1 ObjectMapper 基礎配置

ObjectMapper mapper = new ObjectMapper()
// 常用全域配置
    .configure(SerializationFeature.INDENT_OUTPUT, true)        // 格式化輸出
    .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) // 忽略未知欄位
    .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)    // 日期輸出為 ISO-8601 字串
    .setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"))          // 自定義日期格式
    .setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"))                  // 時區
    .registerModule(new JavaTimeModule())                                // 支援 Java 8 LocalDateTime 等
    .setSerializationInclusion(JsonInclude.Include.NON_NULL);            // 忽略 null 值

1.2 POJO 定義

@Data // Lombok
@NoArgsConstructor @AllArgsConstructor
public class User {
    private Long id;
    private String name;
    private String email;
    private int age;
    @JsonFormat(pattern = "yyyy-MM-dd") // 欄位級日期格式
    private LocalDate birthday;
    @JsonProperty("is_vip") // JSON 鍵名映射
    private boolean vip;
    @JsonIgnore // 序列化忽略
    private String internalToken;
}

1.3 序列化:Java → JSON

User user = new User(1L, "小明", "xm@example.com", 20, LocalDate.of(2004, 1, 1), true, "secret");

// 1. 輸出字串
String json = mapper.writeValueAsString(user);
// {"id":1,"name":"小明","email":"xm@example.com","age":20,"birthday":"2004-01-01","is_vip":true}

// 2. 輸出檔案/流
mapper.writeValue(new File("user.json"), user);
mapper.writeValue(System.out, user);

// 3. 集合序列化
List<User> users = Arrays.asList(user, new User(2L, "小紅", ...));
String jsonList = mapper.writeValueAsString(users);

1.4 反序列化:JSON → Java

String json = "{\"id\":1,\"name\":\"小明\",\"age\":20,\"birthday\":\"2004-01-01\",\"is_vip\":true}";

// 1. 簡單類別
User user = mapper.readValue(json, User.class);

// 2. 泛型集合:需用 TypeReference
List<User> users = mapper.readValue(jsonList, new TypeReference<List<User>>() {});

// 3. 陣列
User[] arr = mapper.readValue(jsonList, User[].class);

// 4. 從檔案/流讀取
User u = mapper.readValue(new File("user.json"), User.class);

二、三大使用模式深度對比

模式核心類特點適用場景
Data BindingObjectMapper最高級抽象,POJO 自動映射,開發效率最高常規業務開發、REST API、配置文件
Tree ModelJsonNode, ObjectNode動態結構,無需預定義 POJO,靈活遍歷/修改動態 JSON、Schema 不固定、中間層轉換
Streaming APIJsonParser, JsonGenerator最低級、零拷貝、記憶體佔用極小、效能最高超大 JSON、高吞吐場景、嵌入式環境

三、Tree Model:動態 JSON 處理

String json = "{\"name\":\"root\",\"children\":[{\"id\":1},{\"id\":2}]}";

// 1. 解析為樹
JsonNode root = mapper.readTree(json);

// 2. 安全取值
String name = root.path("name").asText();           // 找不到返回空字串
JsonNode child0 = root.path("children").get(0);     // 陣列索引
int id = child0.path("id").asInt();

// 3. 構建樹
ObjectNode newRoot = mapper.createObjectNode();
newRoot.put("status", "ok");
ArrayNode arr = mapper.createArrayNode();
arr.add(1).add(2).add(3);
newRoot.set("data", arr);

// 4. 樹轉 POJO / POJO 轉樹
User u = mapper.treeToValue(root, User.class);
JsonNode tree = mapper.valueToTree(user);

四、Streaming API:極致效能

4.1 生成 JSON (JsonGenerator)

try (JsonGenerator gen = mapper.getFactory().createGenerator(new File("out.json"), JsonEncoding.UTF8)) {
    gen.writeStartObject();
    gen.writeStringField("name", "Speedment");
    gen.writeNumberField("version", 3);
    gen.writeFieldName("features");
    gen.writeStartArray();
    gen.writeString("Stream API");
    gen.writeString("Code Generation");
    gen.writeEndArray();
    gen.writeEndObject();
}

4.2 解析 JSON (JsonParser)

try (JsonParser parser = mapper.getFactory().createParser(new File("out.json"))) {
    while (parser.nextToken() != JsonToken.END_OBJECT) {
        String field = parser.getCurrentName();
        if ("name".equals(field)) {
            parser.nextToken(); // 移動到值
            System.out.println(parser.getText());
        } else if ("features".equals(field)) {
            parser.nextToken(); // START_ARRAY
            while (parser.nextToken() != JsonToken.END_ARRAY) {
                System.out.println(parser.getText());
            }
        }
    }
}

五、進階技巧與最佳實務

5.1 多態反序列化(@JsonTypeInfo)

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes({@Type(value = Cat.class, name = "cat"), @Type(value = Dog.class, name = "dog")})
interface Animal { }
{"type":"cat","name":"Kitty"} → 自動反序列化為 Cat 實例

5.2 自定義序列化器/反序列化器

public class LocalDateSerializer extends JsonSerializer<LocalDate> {
    @Override public void serialize(LocalDate d, JsonGenerator g, SerializerProvider p) throws IOException {
        g.writeString(d.format(DateTimeFormatter.ISO_LOCAL_DATE));
    }
}
// 使用:@JsonSerialize(using = LocalDateSerializer.class)

5.3 避免循環引用

@JsonManagedReference // 父端
private List<Child> children;

@JsonBackReference // 子端
private Parent parent;
// 或使用 @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")

5.4 忽略未知/動態屬性

@JsonIgnoreProperties(ignoreUnknown = true) // 類級
@JsonAnySetter // 捕獲動態屬性存入 Map
public void setDynamic(String key, Object value) { dynamicProps.put(key, value); }

5.5 效能優化清單

  • 複用 ObjectMapper:單例,線程安全,避免重複創建開銷。
  • 啟用 Afterburner 模組:mapper.registerModule(new AfterburnerModule()),字節碼生成存取器,提速 20%-30%。
  • 避免大物件圖深度序列化:使用 View (@JsonView) 或 DTO 截斷不必要關聯。
  • 流式處理大數據:mapper.readValues(parser, User.class) 逐條讀取,不載入全量記憶體。
  • 關閉不必要特性:FAIL_ON_UNKNOWN_PROPERTIES=false, WRITE_DATES_AS_TIMESTAMPS=false 等。

六、常見坑點速查

問題原因解決
日期輸出為時間戳預設 WRITE_DATES_AS_TIMESTAMPS=true關閉該特性 + 註冊 JavaTimeModule + @JsonFormat
反序列化報 UnrecognizedPropertyExceptionJSON 含 POJO 無的欄位FAIL_ON_UNKNOWN_PROPERTIES=false 或 @JsonIgnoreProperties
LocalDateTime 無法反序列化缺少 JavaTimeModulemapper.registerModule(new JavaTimeModule())
泛型集合反序列化為 LinkedHashMap類型擦除,未提供 TypeReferencenew TypeReference<List<User>>(){} 或 JavaType
循環引用 StackOverflowError雙向關聯無斷點@JsonManagedReference/@JsonBackReference 或 @JsonIdentityInfo
null 值輸出 "null"預設包含 nullsetSerializationInclusion(NON_NULL) 或 @JsonInclude

七、總結

Jackson 以 ObjectMapper 為核心,提供 Data Binding、Tree Model、Streaming API 三種範式覆蓋從簡單到極致效能的所有場景。掌握註解驅動定制、泛型 TypeReference、日期/多態/循環引用處理、Afterburner 加速、流式大數據處理,即可在生產環境游刃有餘地應對各種 JSON 交互需求。

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