第四步,通过自定义 Converter 进行序列化和反序列化
2026/7/23 15:50:30 网站建设 项目流程

第四步,通过自定义 Converter 进行序列化和反序列化

在软件开发中,序列化和反序列化是数据交换的核心环节。无论是将对象存储到文件、通过网络传输,还是与数据库交互,我们都需要一种机制来将内存中的对象转换为字节流(序列化),以及将字节流还原为对象(反序列化)。虽然许多框架(如 Jackson、Gson)提供了默认的序列化方式,但在实际项目中,我们常常需要自定义 Converter 来满足特定需求,比如处理复杂的日期格式、加密字段、或兼容遗留系统的数据格式。本文将带你深入理解自定义 Converter 的原理,并通过两个实战示例,手把手教你如何实现灵活的序列化和反序列化。## 什么是自定义 Converter?简单来说,Converter 是一个转换器,它定义了如何将一种类型的数据转换为另一种类型。在序列化上下文中,它通常用于:-序列化时:将 Java/Python 对象转换为 JSON/XML/字节流。-反序列化时:将 JSON/XML/字节流还原为对象。默认的序列化工具(如 Python 的json模块)只能处理基本类型(字符串、数字、列表、字典)。当遇到自定义对象(如datetimeDecimal)时,就会报错。自定义 Converter 就是为了解决这类问题而生的。## 为什么需要自定义 Converter?假设你有一个订单系统,其中包含一个created_at字段,类型为datetime。默认的 JSON 序列化器无法直接处理datetime对象。你可能会想到将datetime转换为字符串,但这样一来,反序列化时又需要手动解析字符串。自定义 Converter 可以自动完成这个双向转换。此外,自定义 Converter 还可以:-加密敏感字段:序列化时自动加密,反序列化时自动解密。-兼容旧系统:将新系统的数据格式转换为旧系统能识别的格式。-优化性能:通过自定义转换减少不必要的内存开销。## 示例一:使用 Python 自定义 datetime 转换器在 Python 中,json模块默认不支持datetime对象。我们可以通过继承json.JSONEncoderjson.JSONDecoder来实现自定义 Converter。pythonimport jsonfrom datetime import datetime, date# 自定义序列化器(Encoder)class DateTimeEncoder(json.JSONEncoder): def default(self, obj): # 如果是 datetime 或 date 对象,则转换为 ISO 格式字符串 if isinstance(obj, (datetime, date)): return obj.isoformat() # 其他类型交给默认处理器(或抛出异常) return super().default(obj)# 自定义反序列化器(Decoder)class DateTimeDecoder(json.JSONDecoder): def __init__(self, *args, **kwargs): # 设置自定义的 object_hook,在反序列化时自动处理字典 super().__init__(object_hook=self.object_hook, *args, **kwargs) def object_hook(self, dct): # 遍历字典的键值对 for key, value in dct.items(): # 尝试将 ISO 格式字符串解析为 datetime 对象 if isinstance(value, str): try: # 先尝试解析为 datetime(包含时间部分) dct[key] = datetime.fromisoformat(value) except (ValueError, TypeError): # 如果失败,则保持原样 pass return dct# 测试代码if __name__ == "__main__": # 创建一个包含 datetime 的字典 data = { "name": "Alice", "created_at": datetime.now(), "updated_at": date.today() } # 序列化:使用自定义 Encoder json_str = json.dumps(data, cls=DateTimeEncoder, ensure_ascii=False) print("序列化结果:", json_str) # 反序列化:使用自定义 Decoder restored_data = json.loads(json_str, cls=DateTimeDecoder) print("反序列化后:", restored_data) print("类型验证:", type(restored_data["created_at"])) # 应该是 datetime代码解析:-DateTimeEncoder重写了default方法,当遇到datetimedate对象时,返回 ISO 格式字符串。-DateTimeDecoder通过object_hook钩子,在解析每个字典时尝试将字符串转换为datetime对象。- 这种设计保证了序列化和反序列化的对称性:日期对象 -> 字符串 -> 日期对象。## 示例二:Java 中使用 Jackson 自定义 Converter在 Java 生态中,Jackson 是最流行的 JSON 处理库。很多时候我们需要处理自定义类型,比如将LocalDateTime转换为时间戳,或者对字符串进行加密。下面是一个使用 Jackson 自定义序列化器和反序列化器的完整示例。javaimport com.fasterxml.jackson.core.JsonGenerator;import com.fasterxml.jackson.core.JsonParser;import com.fasterxml.jackson.core.JsonProcessingException;import com.fasterxml.jackson.databind.*;import com.fasterxml.jackson.databind.module.SimpleModule;import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;import java.io.IOException;import java.time.LocalDateTime;import java.time.format.DateTimeFormatter;// 自定义序列化器:将 LocalDateTime 转换为自定义格式字符串class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> { private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); @Override public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException { // 将 LocalDateTime 格式化为 "2023-10-01 12:30:00" gen.writeString(value.format(formatter)); }}// 自定义反序列化器:将自定义格式字符串解析为 LocalDateTimeclass LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> { private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); @Override public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { String dateStr = p.getText(); // 解析字符串为 LocalDateTime return LocalDateTime.parse(dateStr, formatter); }}// 包含 LocalDateTime 字段的 POJO 类class Order { private String orderId; private LocalDateTime createTime; // getter 和 setter 省略(实际开发中请使用 Lombok 或手动生成) public String getOrderId() { return orderId; } public void setOrderId(String orderId) { this.orderId = orderId; } public LocalDateTime getCreateTime() { return createTime; } public void setCreateTime(LocalDateTime createTime) { this.createTime = createTime; }}public class CustomConverterDemo { public static void main(String[] args) throws JsonProcessingException { // 创建一个 ObjectMapper 实例 ObjectMapper mapper = new ObjectMapper(); // 创建自定义模块,并注册序列化器和反序列化器 SimpleModule module = new SimpleModule(); module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer()); module.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer()); // 注册模块到 ObjectMapper mapper.registerModule(module); // 可选:注册 JavaTimeModule 以支持其他日期类型 mapper.registerModule(new JavaTimeModule()); // 创建测试对象 Order order = new Order(); order.setOrderId("ORD001"); order.setCreateTime(LocalDateTime.now()); // 序列化 String json = mapper.writeValueAsString(order); System.out.println("序列化结果: " + json); // 输出类似:{"orderId":"ORD001","createTime":"2023-10-01 12:30:00"} // 反序列化 Order restoredOrder = mapper.readValue(json, Order.class); System.out.println("反序列化后: " + restoredOrder.getCreateTime()); // 输出:2023-10-01T12:30:00(但实际显示取决于 toString 方法) }}代码解析:-LocalDateTimeSerializer继承JsonSerializer,在serialize方法中定义如何将LocalDateTime转换为字符串。-LocalDateTimeDeserializer继承JsonDeserializer,在deserialize方法中定义如何从字符串还原LocalDateTime。- 通过SimpleModule将自定义转换器注册到ObjectMapper,这样在序列化/反序列化时就会自动调用这些转换器。## 总结自定义 Converter 是处理序列化和反序列化时的一把利器。它让我们能够:1.处理非标准类型:如日期、时间、货币、自定义对象等。2.实现业务逻辑:在转换过程中加密、解密、格式化或校验数据。3.保持代码整洁:将转换逻辑集中在一个地方,避免在业务代码中到处手动转换。在实际项目中,建议遵循“单一职责原则”,为每种特殊类型创建独立的 Converter,并通过模块化注册的方式集成到主序列化引擎中。这样既能提高代码的可维护性,又能灵活应对未来可能出现的新的数据类型需求。记住,自定义 Converter 的核心思想是对称性:序列化和反序列化的逻辑应该互为逆操作,这样才能保证数据在转换过程中不丢失信息。掌握了这个原则,你就能轻松驾驭任何复杂的序列化场景。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询