什麼是 Serialization (序列化)?

1
什麼是 Serialization (序列化)?:序列化(Serialization)是程式設計中將物件、資料結構或狀態轉換為可儲存或傳輸的位元組流(byte stream)的過程,反向操作稱為反序列化(Deserialization)。它解決了物件在記憶體中無法直接跨進程、跨網路或持久化儲存的問題,讓複雜資料結構能在檔案、資料庫、快取或 API 中無縫傳遞,是現代應用不可或缺的基礎技術。

什麼是 Serialization (序列化)?

序列化(Serialization)是程式設計中將物件、資料結構或狀態轉換為可儲存或傳輸的位元組流(byte stream)的過程,反向操作稱為反序列化(Deserialization)。它解決了物件在記憶體中無法直接跨進程、跨網路或持久化儲存的問題,讓複雜資料結構能在檔案、資料庫、快取或 API 中無縫傳遞,是現代應用不可或缺的基礎技術。

 

序列化的核心目的與原理

序列化將記憶體中動態物件轉為靜態位元組序列,保留完整結構資訊:

物件狀態 → 序列化 → 位元組流 → 儲存/傳輸 → 反序列化 → 物件狀態
User(id=1, name="Alice") → b'x00x01Alice' → 檔案/網路 → User(id=1, name="Alice")
 

關鍵挑戰

  • 保留類型資訊(String vs int)

  • 處理巢狀物件(物件內含物件)

  • 跨語言/平台相容性

  • 版本相容性(類別結構變更)

 

常見序列化格式比較

格式 可讀性 效能 跨語言 用途 範例
JSON 優秀 API、設定檔 {"name": "Alice", "age": 25}
XML 企業整合、SOAP <user><name>Alice</name></user>
Protocol Buffers 優秀 gRPC、高效能 RPC 08 01 12 05 41 6c 69 63 65
MessagePack 優秀 即時通訊 二進位 JSON
BSON MongoDB JSON 二進位擴展

 

程式語言實作範例

Python(JSON + pickle)

import json
import pickle
from dataclasses import asdict

@dataclass
class User:
    id: int
    name: str
    email: str

user = User(1, "Alice", "[email protected]")

# JSON 序列化(需可轉 JSON)
user_dict = asdict(user)
json_str = json.dumps(user_dict)
print(json_str)  # {"id": 1, "name": "Alice", "email": "[email protected]"}

# Python 原生(pickle,二進位)
serialized = pickle.dumps(user)
deserialized = pickle.loads(serialized)
print(deserialized)  # User(id=1, name='Alice', email='[email protected]')

 

JavaScript(JSON 原生支援)

const user = { id: 1, name: 'Alice', email: '[email protected]' };

// 序列化
const jsonString = JSON.stringify(user);
console.log(jsonString);  // {"id":1,"name":"Alice","email":"[email protected]"}

// 反序列化
const userObj = JSON.parse(jsonString);
console.log(userObj.id);  // 1

 

Java(Jackson + Gson)

import com.fasterxml.jackson.databind.ObjectMapper;

User user = new User(1, "Alice", "[email protected]");
ObjectMapper mapper = new ObjectMapper();

// 序列化
String json = mapper.writeValueAsString(user);

// 反序列化
User deserialized = mapper.readValue(json, User.class);

 

序列化在實際場景的應用

1. Web API 資料交換

// Client → Server
fetch('/api/users', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ name: 'Alice', email: '[email protected]' })
});

// Server → Client
res.json({ id: 1, name: 'Alice', ... });

 

2. 快取系統(Redis)

import redis
import json

r = redis.Redis()
user = User(1, "Alice", "[email protected]")

# 序列化儲存
r.setex("user:1", 3600, json.dumps(asdict(user)))

# 反序列化讀取
user_data = json.loads(r.get("user:1"))

 

3. 訊息佇列(RabbitMQ/Kafka)

# 生產者:序列化發送事件
order_event = {"order_id": 123, "status": "created"}
channel.basic_publish(
    exchange='',
    routing_key='orders',
    body=json.dumps(order_event)
)

# 消費者:反序列化處理
import json
method_frame, header_frame, body = delivery
order = json.loads(body)

 

4. Session 儲存

// Express + Redis Session
app.use(session({
    store: new RedisStore({ client: redisClient }),
    secret: 'keyboard cat',
    resave: false,
    saveUninitialized: false
}));

 

進階序列化協議

Protocol Buffers(protobuf)

// user.proto
syntax = "proto3";
message User {
  int32 id = 1;
  string name = 2;
  string email = 3;
}

# 比 JSON 小 3-10 倍,解析快 5-20 倍
user_proto = User(id=1, name="Alice", email="[email protected]")
serialized = user_proto.SerializeToString()
 

Apache Avro

  • Schema 內嵌,支援 Schema 演化

  • 動態類型,跨語言

  • Hadoop 生態標準

 

序列化安全挑戰

反序列化漏洞(常見資安問題):

// Java 反序列化 RCE 漏洞
ObjectInputStream ois = new ObjectInputStream(input);
Object obj = ois.readObject();  // 危險!可遠端執行程式碼
 

解決方案

  • 使用 JSON/XML(安全)

  • 白名單序列化類別

  • 限制反序列化深度

  • 改用安全協議(protobuf)

 

效能與大小比較

原始物件:User {id:1, name:"Alice", email:"[email protected]"}
JSON:    52 bytes
XML:     98 bytes
protobuf:16 bytes (67% 壓縮)
MessagePack:38 bytes


實際效能(1M 物件):

JSON 序列化:1.2s / 反序列化:1.1s
protobuf:0.2s / 0.18s (5-6x 加速)
 

最佳實務與注意事項

選擇原則

API 外部:JSON(通用、人可讀)
內部 RPC:protobuf/gRPC(效能)
快取:MessagePack(壓縮)
資料庫:原生格式或 BSON
 

程式碼實務

# 版本控制
class UserV1:
    id: int
    name: str

class UserV2(UserV1):
    id: int
    name: str
    email: str  # 向後相容

# 驗證序列化資料
def safe_deserialize(data):
    try:
        obj = json.loads(data)
        UserSchema().load(obj)  # pydantic 驗證
        return obj
    except ValidationError:
        raise ValueError("無效資料格式")
 

常見錯誤

# 忘記處理 None/null
json.dumps({'user': None})  # 跨語言問題

# 循環引用
class Node:
    def __init__(self, value, next=None):
        self.value = value
        self.next = next  # 序列化無限循環
 

序列化是分散式系統的血液,從 REST API 到微服務通訊,從快取到訊息佇列,無處不在。選擇適合格式(JSON 通用、protobuf 效能)、注意安全(避免反序列化漏洞)、支援版本演化,就能打造可靠的資料交換管道,提升系統效能與穩定性。