1. Tại sao phải chọn định dạng? Nhắc lại ngắn gọn
Bất kỳ đối tượng .NET nào trong bộ nhớ — là một tập địa chỉ, tham chiếu, field, cấu trúc nội bộ và các "máy móc" khác. Nhưng lưu trực tiếp vào file thì không ổn: file phải được cấu trúc theo định dạng mà không chỉ mình ta mà cả chương trình khác có thể đọc (và tốt nhất là ghi) được. Đây là lúc bạn phải chọn định dạng serialization.
Nhiệm vụ chính của định dạng serialization:
- Tính gọn: chiếm ít chỗ đĩa hoặc nhanh khi truyền mạng.
- Tính dễ đọc (cho con người!): có mở file bằng editor và hiểu được nội dung không.
- Tính phổ quát: có phù hợp tích hợp với hệ thống/ngôn ngữ khác không.
- Hỗ trợ cấu trúc phức tạp: nested, collection, reference, types.
- Bảo mật và tương thích.
2. Binary Serialization (Serial hóa nhị phân)
Binary Serialization biểu diễn dữ liệu dưới dạng "thô" một luồng byte nhị phân. Hãy tưởng tượng bạn không chỉ xếp đồ vào hộp mà còn đổ bê tông vào — nhanh, gọn, nhưng sau đó bạn sẽ không tìm được đôi tất của mình nếu không có búa.
// Primer chỉ để tham khảo lịch sử:
using System.Runtime.Serialization.Formatters.Binary;
// ... tạo đối tượng
var user = new User { Name = "Ivan", Age = 42 };
// Serialization
using var fs = new FileStream("user.bin", FileMode.Create);
var formatter = new BinaryFormatter();
formatter.Serialize(fs, user);
Ưu:
- Gọn: chiếm ít không gian đĩa, tốc độ cao.
- Hỗ trợ tích hợp các .NET-native types.
Nhược:
- Định dạng hoàn toàn không đọc được — mở bằng Notepad bạn sẽ thấy một mớ ký tự rác.
- Hoàn toàn không phổ quát: chỉ dành cho .NET (và còn phụ thuộc version nữa!).
- Dễ gặp vấn đề tương thích giữa các phiên bản.
Dùng ở đâu?
Trong .NET khi cần "dump" đối tượng giữa các process trên cùng máy. Hiện nay cực kỳ KHÔNG được khuyến nghị, đặc biệt nếu bạn quan tâm đến bảo mật và bảo trì lâu dài. Dùng BinaryFormatter trong dự án hiện đại là practice tồi.
3. Định dạng XML (Extensible Markup Language)
XML — định dạng đọc được bởi người và máy, dựa trên tag giống HTML, nhưng không có mấy trò đùa về <body>.
<User>
<Name>Ivan</Name>
<Age>42</Age>
</User>
Ví dụ serialization:
using System.Xml.Serialization;
var user = new User { Name = "Ivan", Age = 42 };
var serializer = new XmlSerializer(typeof(User));
using var fs = new FileStream("user.xml", FileMode.Create);
serializer.Serialize(fs, user);
Ưu:
- Dễ đọc: mở file là thấy cấu trúc.
- Phổ quát: nhiều ngôn ngữ và chương trình đọc được XML.
- Linh hoạt (hỗ trợ schema, validation, namespaces, v.v.).
- Phù hợp cho cấu trúc phức tạp và đối tượng lồng nhau.
Nhược:
- Verbose và nặng: chiếm nhiều chỗ và băng thông.
- Parsing chậm hơn so với định dạng nhị phân.
- Một số loại như date/time có thể bị serialize không chính xác nếu không cấu hình.
- Cần cấu hình thêm để hỗ trợ một số collection hoặc object bất thường.
Dùng ở đâu?
Trao đổi dữ liệu giữa hệ thống doanh nghiệp, config, tích hợp với hệ thống yêu cầu cấu trúc nghiêm ngặt.
4. Định dạng JSON (JavaScript Object Notation)
JSON — gọn nhẹ, dễ đọc, tới từ thế giới JavaScript và gần như thống trị trong truyền dữ liệu nhờ ngắn gọn và đơn giản.
{
"Name": "Ivan",
"Age": 42
}
Ví dụ serialization:
using System.Text.Json;
var user = new User { Name = "Ivan", Age = 42 };
string json = JsonSerializer.Serialize(user);
File.WriteAllText("user.json", json);
Ưu:
- Rất dễ đọc cả cho người và máy.
- Dễ tích hợp với web technologies (API, JavaScript, v.v.).
- Gọn hơn XML.
- Serialize/deserialize nhanh với thư viện hiện đại (System.Text.Json, Newtonsoft.Json).
Nhược:
- Không hỗ trợ comments (JSON không thể tự trêu mình đâu).
- Giới hạn cấu trúc: không serialize được reference giữa object hoặc các type phức tạp (ví dụ dictionary với non-string keys).
- Sự khác nhau trong cách biểu diễn date/time giữa các implement khác nhau.
Dùng ở đâu?
Gần như ở mọi nơi cần trao đổi giữa nền tảng: web services, mobile apps, REST API, v.v.
5. CSV (Comma-Separated Values)
CSV — định dạng text đơn giản, biểu diễn dữ liệu dạng bảng (rows và columns), các field phân tách bằng comma hoặc ký tự khác.
Name,Age
Ivan,42
Olga,27
Ví dụ ghi CSV thủ công:
// Cho đơn giản, ghi bằng StreamWriter bình thường
var lines = new List<string>
{
"Name,Age",
"Ivan,42",
"Olga,27"
};
File.WriteAllLines("users.csv", lines);
Ưu:
- Được hỗ trợ rộng rãi (Excel, Google Docs, DB, v.v.).
- Ngắn gọn, phù hợp dữ liệu dạng bảng.
Nhược:
- Không phù hợp cho object lồng nhau hoặc phức tạp (chỉ cho cấu trúc "phẳng").
- Không lưu kiểu dữ liệu (mọi thứ là string).
- Khó xử lý escaping nếu dữ liệu chứa comma, quote, newline.
Dùng ở đâu?
Export/import giữa DB, trao đổi bộ ghi đơn giản, xuất dữ liệu từ ứng dụng.
6. Protocols và định dạng với strong typing
Protocol Buffers (protobuf) và MessagePack — định dạng nhị phân có contract (schema), làm serialization nhỏ hơn và nhanh hơn. Chúng yêu cầu mô tả schema trước.
Ví dụ protobuf (đơn giản):
Không nằm trong chuẩn .NET, cần package Google.Protobuf.
message User {
string name = 1;
int32 age = 2;
}
Ưu:
- Tốc độ và độ gọn tối đa.
- Cross-platform (nhiều ngôn ngữ hỗ trợ protobuf).
Nhược:
- Khó học và cấu hình hơn.
- Cần generate code từ schema.
- Không phải lúc nào cũng cần thiết nếu dự án không xử lý triệu thông điệp/giây.
Dùng ở đâu?
Hệ thống tải cao, trao đổi giữa microservices, game, IoT.
7. Những nuance hữu ích
Bảng so sánh các định dạng
| Định dạng | Đọc được | Gọn | Phổ quát | Đối tượng phức tạp | Standard trong .NET 9 | Bảo mật |
|---|---|---|---|---|---|---|
| Binary (.NET) | Không | Có | Không | Có | Không | Không |
| XML | Có | Không | Có | Có | Có | Có |
| JSON | Có | Có | Có | Một phần | Có | Có |
| CSV | Có | Có | Có | Không | Không | Có |
| Protobuf | Không | Tốt nhất | Có | Có | Không | Có |
Làm sao chọn định dạng cho app của bạn?
Bạn lưu cấu trúc phức tạp và muốn người có thể đọc được — dùng XML hoặc JSON.
Cần truyền nhanh khối lượng lớn dữ liệu giữa service bạn kiểm soát — cân nhắc protobuf hoặc MessagePack.
Xuất báo cáo phân tích vào Excel hoặc DB — dùng CSV.
Viết config cho services hoặc CI/CD — YAML sẽ cứu bạn nhiều lúc.
Gọn, nhanh và cần hỗ trợ reference giữa object — quan trọng? Tìm định dạng nhị phân, nhưng nhớ các nhược điểm về bảo mật và tương thích.
8. Những mánh và lỗi hay gặp
Nếu bạn quyết định lưu dưới dạng nhị phân để "bí mật", nhớ: dump nhị phân không đồng nghĩa an toàn. Kẻ tấn công vẫn có thể phân tích luồng đó. Dùng encryption khi cần.
Vấn đề phổ biến: quên encoding khi làm việc với text formats (XML/JSON/CSV) — dùng UTF-8. Không phải editor hoặc hệ thống nào cũng thích BOM.
XML, dù có vẻ "cũ", vẫn tốt cho các protocol hợp đồng, nơi cần mô tả validation rõ ràng (ví dụ XSD), còn JSON thì tiện cho trao đổi nhanh, linh hoạt.
Khi serialize collection của object phức tạp không phải định dạng nào cũng hỗ trợ đúng cho nested hoặc recursive structures. JSON và XML chơi tốt với arrays và lists, CSV thì không.
GO TO FULL VERSION