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

Java 序列化與 JSON 序列化完整指南:預設二進制 vs Jackson

     編輯:Java 程式設計入門

物件持久化與網路傳輸是 Java 開發核心場景。本文對比 JDK 內建序列化與 Jackson JSON 序列化,提供可直接運行的完整範例,幫助你根據效能、相容性、可讀性選擇最適方案。

一、JDK 內建序列化(二進制格式)

1.1 核心機制

  • 類別需實作 Serializable 介面(標記介面,無方法)。
  • 透過 ObjectOutputStream / ObjectInputStream 進行寫入與讀取。
  • 序列化包含類別元資料、欄位值、物件圖參考,輸出為二進制位元組流。

1.2 基本用法

// 序列化
try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("data.bin"))) {
    out.writeObject(myObject);
}

// 反序列化
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.bin"))) {
    MyClass obj = (MyClass) in.readObject();
}

1.3 關鍵注意點

  • serialVersionUID:建議顯式宣告,避免類別變更導致 InvalidClassException。
  • transient:標記不需序列化的欄位(如密碼、暫存計算結果)。
  • 安全風險:反序列化不可信資料可能導致 RCE,生產環境嚴禁直接反序列化外部輸入。

二、Jackson JSON 序列化(文本格式)

2.1 為何選擇 Jackson?

  • 高效能、低記憶體佔用、支援流式處理。
  • 豐富註解(@JsonIgnore、@JsonProperty、@JsonFormat)靈活控制輸出。
  • 跨語言、人類可讀、易於除錯與日誌記錄。

2.2 核心 API

ObjectMapper mapper = new ObjectMapper();
// 序列化為檔案
mapper.writeValue(new File("data.json"), myObject);
// 序列化為字串
String json = mapper.writeValueAsString(myObject);

// 反序列化
MyClass obj = mapper.readValue(new File("data.json"), MyClass.class);
MyClass obj2 = mapper.readValue(jsonString, MyClass.class);

2.3 常用配置

mapper.configure(SerializationFeature.INDENT_OUTPUT, true); // 美化輸出
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // 忽略未知欄位
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); // 日期格式

三、完整可運行範例:Zoo 類別示範

以下整合兩種序列化方式,展示靜態欄位、集合、自訂 toString 的處理差異。

import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.*;
import java.util.ArrayList;

public class Zoo implements Serializable {
    private static final long serialVersionUID = 1L;
    private static final ObjectMapper MAPPER = new ObjectMapper();

    public static int maxAnimalCount;
    public ArrayList animals = new ArrayList<>();

    public void addAnimal(String name) {
        if (animals.size() < maxAnimalCount) animals.add(name);
    }

    // --- JDK 序列化 ---
    public void serializeToLog(String path) {
        try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(path))) {
            out.writeObject(this);
        } catch (IOException e) { e.printStackTrace(); }
    }

    public static Zoo deserializeFromLog(String path) {
        try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(path))) {
            return (Zoo) in.readObject();
        } catch (Exception e) { e.printStackTrace(); return null; }
    }

    // --- Jackson JSON 序列化 ---
    public void serializeJSONToLog(String path) {
        try { MAPPER.writeValue(new File(path), this); }
        catch (IOException e) { e.printStackTrace(); }
    }

    public static Zoo deserializeJSONFromLog(String path) {
        try { return MAPPER.readValue(new File(path), Zoo.class); }
        catch (IOException e) { e.printStackTrace(); return null; }
    }

    @Override public String toString() {
        return "Zoo{animals=" + animals + ", max=" + maxAnimalCount + "}";
    }

    // --- 測試主程式 ---
    public static void main(String[] args) {
        Zoo zoo1 = new Zoo(); Zoo.setMax(100);
        zoo1.addAnimal("hamster"); zoo1.addAnimal("sheep");
        zoo1.serializeToLog("zoo1.bin");
        zoo1.serializeJSONToLog("zoo1.json");

        Zoo zoo2 = Zoo.deserializeFromLog("zoo1.bin");
        Zoo zoo3 = Zoo.deserializeJSONFromLog("zoo1.json");
        System.out.println("JDK 反序列化: " + zoo2);
        System.out.println("JSON 反序列化: " + zoo3);
    }
}

四、深度對比表

維度JDK 序列化Jackson JSON
資料格式二進制UTF-8 文本
跨語言支援極差極佳
可讀性/除錯不可讀人類可讀
效能(大物件)較快略慢(可用流式優化)
版本演進脆弱(需 serialVersionUID)彈性(忽略未知欄位)
安全性高風險(反序列化漏洞)低風險(無程式碼執行)
適用場景JVM 內部 RPC、暫存REST API、設定檔、日誌、跨系統

五、最佳實踐建議

  1. 對外介面、持久化設定、日誌:優先 Jackson JSON。
  2. JVM 內部高效能傳遞、Session 複寫:可考慮 JDK 序列化或更高效的 Protobuf/Kryo。
  3. 混合場景:核心領域模型實作 Serializable,對外 DTO 使用 Jackson 註解控制。
  4. 安全加固:若必須反序列化外部二進制資料,請使用 ObjectInputFilter (Java 9+) 白名單機制。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved