CodeGym /課程 /C# SELF /主要的序列化格式: XML,

主要的序列化格式: XML, JSON, CSV, Protobuf

C# SELF
等級 43 , 課堂 2
開放

1. 為什麼需要選擇格式?簡短提醒

任何 .NET 物件在記憶體裡 — 都是地址、參考、欄位、內部結構和其他「機器裡的東西」的集合。但這樣直接存成檔案不行:檔案必須以一種結構化的格式保存,其他程式不只要能讀,最好也能寫。這時就出現了序列化格式的選擇。

序列化格式的主要任務:

  • 緊湊性:磁碟空間或網路傳輸速度。
  • 可讀性(對人!):能否在文字編輯器中打開並理解內容。
  • 通用性:是否適合與其他系統和語言整合。
  • 支援複雜結構:巢狀、集合、參考、型別。
  • 安全性與相容性。

2. 二進位序列化 (Binary Serialization)

二進位序列化把資料表示成「原始」的位元組流。想像你不只是把東西放進箱子,而是把它們用水泥封住 — 快速、緊湊,但之後要取出自己的襪子可能得動用震動鑽。

// 示例僅作歷史參考:
using System.Runtime.Serialization.Formatters.Binary;

// ... 創建物件
var user = new User { Name = "伊萬", Age = 42 };

// 序列化
using var fs = new FileStream("user.bin", FileMode.Create);
var formatter = new BinaryFormatter();
formatter.Serialize(fs, user);

優點:

  • 緊湊:佔用磁碟空間極少,速度高。
  • 內建支援 .NET 的「原生」型別。

缺點:

  • 格式完全不可讀 — 試著用記事本打開,會進入「矩陣」般的亂碼(就是不可讀)。
  • 絕對不具通用性:只能用於 .NET(而且通常僅限於相同版本!)。
  • 對版本間相容性非常脆弱。

以前哪裡用過?

在 .NET 內部,用於在同一台機器上的進程之間快速「dump」物件。現在強烈建議不要用,尤其如果你關心安全性和長期維護。現代專案中使用 BinaryFormatter 是很差的做法。

3. XML 格式 (Extensible Markup Language)

XML是一種人機皆可讀的標記格式,基於標籤,類似 HTML,但沒有那些關於 <body> 的花哨玩笑。

<User>
  <Name>伊萬</Name>
  <Age>42</Age>
</User>

序列化示例:

using System.Xml.Serialization;

var user = new User { Name = "伊萬", Age = 42 };

var serializer = new XmlSerializer(typeof(User));
using var fs = new FileStream("user.xml", FileMode.Create);
serializer.Serialize(fs, user);

優點:

  • 可讀性:可以直接看出結構。
  • 通用性:很多語言和程式都能讀 XML。
  • 彈性(支援 schema、驗證、命名空間等)。
  • 適合複雜結構和巢狀物件。

缺點:

  • 冗長且笨重:佔空間多、傳輸成本高。
  • 解析速度通常比二進位格式慢。
  • 某些型別序列化時不夠精確(例如日期和時間)。
  • 對某些集合或非標準物件需要額外設定。

應用場景?

企業系統之間的資料交換、配置檔、需要嚴格結構描述的整合場景。

4. JSON 格式 (JavaScript Object Notation)

JSON 是一種緊湊、輕量且易讀的格式,起源於 JavaScript 世界,憑藉其簡潔性和易用性幾乎稱霸了資料交換領域。

{
  "Name": "伊萬",
  "Age": 42
}

序列化示例:

using System.Text.Json;

var user = new User { Name = "伊萬", Age = 42 };

string json = JsonSerializer.Serialize(user);
File.WriteAllText("user.json", json);

優點:

  • 對人和機器都非常可讀。
  • 容易與網路技術整合(API、JavaScript 等)。
  • 比 XML 更緊湊。
  • 在現代庫中序列化/反序列化速度快(例如 System.Text.Json, Newtonsoft.Json)。

缺點:

  • 不支援註解(你的 JSON 無法自嘲)。
  • 結構上有限制:例如無法直接序列化物件間的參考或某些複雜型別(比如鍵不是字串的字典)。
  • 不同實現之間的日期/時間格式可能會有差異。

應用場景?

幾乎所有需要跨平台資料交換的地方:網路服務、行動應用、REST API 等。

5. CSV (Comma-Separated Values)

CSV 是一種簡單的文字格式,把資料表示成表格(列與欄),欄位以逗號或其他符號分隔。

Name,Age
伊萬,42
奧爾嘉,27

手動寫入 CSV 的示例:

// 為簡單起見,通過普通 StreamWriter 寫入
var lines = new List<string>
{
    "Name,Age",
    "伊萬,42",
    "奧爾嘉,27"
};
File.WriteAllLines("users.csv", lines);

優點:

  • 被大量程式支援(Excel、Google Docs、資料庫等)。
  • 簡潔,適合表格型資料。

缺點:

  • 不適合巢狀或複雜物件(只能是「扁平」結構)。
  • 不儲存型別資訊(全部都是字串)。
  • 遇到逗號、引號、換行時需要轉義,容易出錯。

應用場景?

在資料庫之間匯出/匯入、交換簡單記錄集、從應用匯出資料用於分析。

6. 帶強型別契約的協定與格式

Protocol Buffers (protobuf)MessagePack 是具有契約(schema)的二進位序列化格式,能使序列化更緊湊、更快。它們需要事先定義資料結構的 schema。

protobuf 的簡化示例:

不是 .NET 標準的一部分,需要套件 Google.Protobuf

message User {
  string name = 1;
  int32 age = 2;
}

優點:

  • 極致的速度和緊湊性。
  • 跨平台(很多語言支援 protobuf)。

缺點:

  • 學習和設定較複雜。
  • 需要基於 schema 生成程式碼。
  • 如果專案不是要處理每秒數百萬條訊息,很多時候用不到它的全部優勢。

應用場景?

高負載系統、微服務間的資料交換、遊戲、IoT 等。

7. 有用的細節

格式比較表

格式 可讀性 緊湊性 通用性 複雜物件 .NET 9 標準 安全性
Binary (.NET)
XML
JSON 部分
CSV
Protobuf 最佳

如何為你的應用選擇序列化格式?

如果要保存複雜資料結構且你重視人工可讀性 — 用 XML 或 JSON。

如果需要在你控制的服務間快速傳送大量資料 — 考慮 protobuf 或 MessagePack。

如果是為了在 Excel 或資料庫中分析導出報表 — 用 CSV。

如果是在為服務或 CI/CD 寫配置檔 — YAML 通常很實用。

如果緊湊性、速度和物件間參考支援是關鍵 — 要找二進位格式,但要記得它們在安全性和相容性上的缺點。

8. 狡猾的細節和常見錯誤

如果你打算把資料存在二進位格式以為「安全隱秘」,記住:二進位 dump 並不等於安全。攻擊者仍有可能反解析那個位元流。需要時請使用加密。

常見問題:在處理文字格式(XML/JSON/CSV)時忘了編碼 — 使用 UTF-8。不是所有編輯器和系統都喜歡 BOM。

XML 看起來「老舊」,但對於需要嚴格契約(比如 XSD schema)的協定仍然很有用;JSON 則適合快速、靈活的交換。

在序列化複雜物件集合時,不是所有格式都能正確支援巢狀或遞迴結構。JSON 和 XML 對陣列與清單支持良好,而 CSV 則不支援。

留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION