Python对象序列化和反序列化方法总结

在Python中,序列化和反序列化对象有多种方法。以下是主要的方法和示例:

1. 使用 pickle 模块(最常用)

pickle 是Python的标准序列化模块,可以处理大多数Python对象。

基本使用

python 复制代码
import pickle

# 定义一个示例对象
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def __repr__(self):
        return f"Person(name={self.name}, age={self.age})"

# 创建对象
person = Person("Alice", 30)

# 序列化(对象 → 字节流)
serialized = pickle.dumps(person)
print(f"序列化结果: {serialized[:50]}...")

# 反序列化(字节流 → 对象)
deserialized = pickle.loads(serialized)
print(f"反序列化结果: {deserialized}")

# 序列化到文件
with open('person.pkl', 'wb') as f:
    pickle.dump(person, f)

# 从文件反序列化
with open('person.pkl', 'rb') as f:
    loaded_person = pickle.load(f)
print(f"从文件加载: {loaded_person}")

处理复杂对象

python 复制代码
import pickle

class Company:
    def __init__(self, name, employees):
        self.name = name
        self.employees = employees

# 嵌套对象
employees = [Person("Bob", 25), Person("Charlie", 35)]
company = Company("TechCorp", employees)

# 序列化
data = pickle.dumps(company)
restored = pickle.loads(data)
print(restored.name)  # TechCorp
print(restored.employees)  # [Person(name=Bob, age=25), ...]

2. 使用 json 模块

JSON更适合跨语言的数据交换,但只能处理基本数据类型。

python 复制代码
import json

# 基本类型
data = {
    "name": "Alice",
    "age": 30,
    "hobbies": ["reading", "hiking"]
}

# 序列化为JSON字符串
json_str = json.dumps(data, indent=2)
print(json_str)

# 反序列化
parsed = json.loads(json_str)
print(parsed["name"])  # Alice

# 处理自定义对象
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def to_dict(self):
        return {"name": self.name, "age": self.age}
    
    @classmethod
    def from_dict(cls, data):
        return cls(data["name"], data["age"])

person = Person("Bob", 25)

# 自定义序列化
person_dict = person.to_dict()
json_str = json.dumps(person_dict)
print(json_str)  # {"name": "Bob", "age": 25}

# 自定义反序列化
loaded_dict = json.loads(json_str)
loaded_person = Person.from_dict(loaded_dict)
print(loaded_person.name)  # Bob

3. 使用 json 模块的自定义编码器/解码器

python 复制代码
import json
from datetime import datetime

class PersonEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, Person):
            return {
                "__person__": True,
                "name": obj.name,
                "age": obj.age
            }
        elif isinstance(obj, datetime):
            return {"__datetime__": obj.isoformat()}
        return super().default(obj)

class PersonDecoder(json.JSONDecoder):
    def __init__(self, *args, **kwargs):
        super().__init__(object_hook=self.object_hook, *args, **kwargs)
    
    def object_hook(self, dct):
        if "__person__" in dct:
            return Person(dct["name"], dct["age"])
        if "__datetime__" in dct:
            return datetime.fromisoformat(dct["__datetime__"])
        return dct

# 使用自定义编码器
person = Person("Alice", 30)
json_str = json.dumps(person, cls=PersonEncoder)
print(json_str)

# 使用自定义解码器
restored = json.loads(json_str, cls=PersonDecoder)
print(restored.name)  # Alice

4. 使用 dataclasses 和 asdict(Python 3.7+)

python 复制代码
from dataclasses import dataclass, asdict
from typing import List
import json

@dataclass
class Address:
    street: str
    city: str

@dataclass
class Employee:
    name: str
    age: int
    address: Address
    skills: List[str]

# 创建对象
address = Address("123 Main St", "New York")
employee = Employee("Alice", 30, address, ["Python", "Java"])

# 序列化
employee_dict = asdict(employee)
json_str = json.dumps(employee_dict, indent=2)
print(json_str)

# 反序列化
def from_dict(cls, data):
    return cls(**data)

loaded_dict = json.loads(json_str)
loaded_employee = Employee(**loaded_dict)
print(loaded_employee.name)  # Alice

5. 使用 getstatesetstate 自定义pickle行为

python 复制代码
import pickle

class SecurePerson:
    def __init__(self, name, age, password):
        self.name = name
        self.age = age
        self._password = password  # 敏感信息
    
    def __getstate__(self):
        # 在序列化时排除敏感信息
        state = self.__dict__.copy()
        del state['_password']
        return state
    
    def __setstate__(self, state):
        # 反序列化时恢复对象
        self.__dict__.update(state)
        self._password = None  # 密码不恢复

person = SecurePerson("Alice", 30, "secret123")
serialized = pickle.dumps(person)
restored = pickle.loads(serialized)

print(restored.name)  # Alice
print(restored._password)  # None (密码被安全处理)

6. 使用第三方库

dill(扩展的pickle)

python 复制代码
import dill  # pip install dill

# dill可以序列化更多Python对象,包括lambda函数
func = lambda x: x * 2
serialized = dill.dumps(func)
restored = dill.loads(serialized)
print(restored(5))  # 10

marshmallow(更结构化的序列化)

python 复制代码
from marshmallow import Schema, fields  # pip install marshmallow

class PersonSchema(Schema):
    name = fields.Str()
    age = fields.Int()

person = {"name": "Alice", "age": 30}
schema = PersonSchema()

# 序列化
result = schema.dump(person)
print(result)  # {'name': 'Alice', 'age': 30}

# 反序列化
data = {"name": "Bob", "age": "25"}  # 注意age是字符串
loaded = schema.load(data)
print(loaded)  # {'name': 'Bob', 'age': 25}

选择建议

  1. pickle:Python内部使用,需要序列化复杂对象或整个对象图
  2. json:跨语言、网络传输、配置文件
  3. dataclasses + json:结构化数据,类型安全
  4. marshmallow:API开发,需要数据验证
  5. dill:需要序列化lambda、闭包等特殊对象

注意事项

  • pickle不能序列化文件句柄、数据库连接等资源
  • pickle有安全风险,不要反序列化不可信的来源
  • JSON只能序列化基本数据类型,需要自定义编码器处理复杂对象
  • 考虑版本兼容性,特别是当数据结构变化时
相关推荐
zjy277771 分钟前
Layui tab选项卡如何动态根据ID值进行程序化切换
jvm·数据库·python
Slow菜鸟3 分钟前
Codex CLI 教程(五)| AI 驱动项目从零到一:面向 Java 全栈工程师打造个人 ECC(V2版)
java·开发语言·人工智能
lsx2024063 分钟前
Julia 基本运算符
开发语言
m0_602857764 分钟前
Redis如何修复槽位分配重叠的脏状态_使用redis-cli --cluster fix工具扫描并修复不一致的Slot
jvm·数据库·python
2301_7662834418 分钟前
怎样开启phpMyAdmin的操作审计日志_记录每条执行的SQL
jvm·数据库·python
tang7778924 分钟前
代理IP质量检测实战:Python实现IP可用性、延迟、匿名度自动测试脚本
大数据·爬虫·python·网络协议·tcp/ip
2501_9216494934 分钟前
企业定制金融数据 API:从架构设计到 Python 接入实战
大数据·开发语言·python·websocket·金融·量化
直奔標竿37 分钟前
SpringAI + RAG + MCP + Agent 零基础全栈实战(完结篇)| 27课完整汇总,Java开发者AI转型必看
java·开发语言·人工智能·spring boot·后端·spring
2601_956139421 小时前
政府事业机构品牌策划公司哪家专业
大数据·人工智能·python
Jmayday1 小时前
Pytorch:AI歌词生成器
人工智能·pytorch·python