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

第四步,通过自定义 Converter 进行序列化和反序列化
第四步通过自定义 Converter 进行序列化和反序列化在软件开发中序列化和反序列化是数据交换的核心环节。无论是将对象存储到文件、通过网络传输还是与数据库交互我们都需要一种机制来将内存中的对象转换为字节流序列化以及将字节流还原为对象反序列化。虽然许多框架如 Jackson、Gson提供了默认的序列化方式但在实际项目中我们常常需要自定义 Converter 来满足特定需求比如处理复杂的日期格式、加密字段、或兼容遗留系统的数据格式。本文将带你深入理解自定义 Converter 的原理并通过两个实战示例手把手教你如何实现灵活的序列化和反序列化。## 什么是自定义 Converter简单来说Converter 是一个转换器它定义了如何将一种类型的数据转换为另一种类型。在序列化上下文中它通常用于-序列化时将 Java/Python 对象转换为 JSON/XML/字节流。-反序列化时将 JSON/XML/字节流还原为对象。默认的序列化工具如 Python 的json模块只能处理基本类型字符串、数字、列表、字典。当遇到自定义对象如datetime、Decimal时就会报错。自定义 Converter 就是为了解决这类问题而生的。## 为什么需要自定义 Converter假设你有一个订单系统其中包含一个created_at字段类型为datetime。默认的 JSON 序列化器无法直接处理datetime对象。你可能会想到将datetime转换为字符串但这样一来反序列化时又需要手动解析字符串。自定义 Converter 可以自动完成这个双向转换。此外自定义 Converter 还可以-加密敏感字段序列化时自动加密反序列化时自动解密。-兼容旧系统将新系统的数据格式转换为旧系统能识别的格式。-优化性能通过自定义转换减少不必要的内存开销。## 示例一使用 Python 自定义 datetime 转换器在 Python 中json模块默认不支持datetime对象。我们可以通过继承json.JSONEncoder和json.JSONDecoder来实现自定义 Converter。pythonimport jsonfrom datetime import datetime, date# 自定义序列化器Encoderclass DateTimeEncoder(json.JSONEncoder): def default(self, obj): # 如果是 datetime 或 date 对象则转换为 ISO 格式字符串 if isinstance(obj, (datetime, date)): return obj.isoformat() # 其他类型交给默认处理器或抛出异常 return super().default(obj)# 自定义反序列化器Decoderclass DateTimeDecoder(json.JSONDecoder): def __init__(self, *args, **kwargs): # 设置自定义的 object_hook在反序列化时自动处理字典 super().__init__(object_hookself.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, clsDateTimeEncoder, ensure_asciiFalse) print(序列化结果:, json_str) # 反序列化使用自定义 Decoder restored_data json.loads(json_str, clsDateTimeDecoder) print(反序列化后:, restored_data) print(类型验证:, type(restored_data[created_at])) # 应该是 datetime代码解析-DateTimeEncoder重写了default方法当遇到datetime或date对象时返回 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 JsonSerializerLocalDateTime { 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 JsonDeserializerLocalDateTime { 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 的核心思想是对称性序列化和反序列化的逻辑应该互为逆操作这样才能保证数据在转换过程中不丢失信息。掌握了这个原则你就能轻松驾驭任何复杂的序列化场景。