1. 概述

本文将介绍如何使用 Jackson 库处理 java.sql.Blob 类型的序列化和反序列化。Blob(二进制大对象)在 Java 中用于存储大量二进制数据,比如图片、文件等。在 JSON 序列化/反序列化过程中,Jackson 默认不支持 Blob 类型,但我们可以通过自定义序列化器和反序列化器来解决这个问题。

我们将从环境搭建和示例代码开始,逐步实现自定义序列化器和反序列化器,最后通过单元测试验证方案的有效性。整个过程简单粗暴,但能解决实际开发中的痛点。

2. 依赖和示例准备

首先确保项目中包含 Jackson 核心依赖 jackson-databind。在 Maven 项目的 pom.xml 中添加:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.12.3</version>
</dependency>

接下来创建一个包含 Blob 字段的 POJO 类作为示例。这里我们定义一个 User 类,包含 idnameprofilePicture(头像)字段:

public class User {
    private int id;
    private String name;
    private Blob profilePicture;
    // 构造方法
    // Getter 和 Setter
}

这个 User 类将用于后续演示 Blob 字段的序列化和反序列化操作。

3. 定义 Blob 序列化器

创建自定义序列化器将 Blob 转换为 Base64 编码的二进制字符串:

@JacksonStdImpl
public class SqlBlobSerializer extends JsonSerializer<Blob> {
    @Override
    public void serialize(Blob value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        try {
            byte[] blobBytes = value.getBytes(1, (int) value.length());
            gen.writeBinary(blobBytes);
        } catch (Exception e) {
            throw new IOException("Failed to serialize Blob", e);
        }
    }
}

关键点解析:

  • @JacksonStdImpl 注解标记这是 Jackson 的标准序列化器实现
  • ✅ 继承 JsonSerializer<Blob> 泛型类
  • serialize() 方法核心逻辑:
    1. 通过 getBytes() 提取 Blob 的字节数组
    2. 使用 gen.writeBinary() 写入 Base64 编码的二进制数据

⚠️ 注意:getBytes(1, length) 中的起始位置是 1(JDBC 规范要求),这是常见的踩坑点。

5. 定义 Blob 反序列化器

创建反序列化器将 Base64 字符串还原为 Blob 对象:

@JacksonStdImpl
public class SqlBlobDeserializer extends JsonDeserializer<Blob> {
    @Override
    public Blob deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        try {
            byte[] blobBytes = p.getBinaryValue();
            return new SerialBlob(blobBytes);
        } catch (Exception e) {
            throw new IOException("Failed to deserialize Blob", e);
        }
    }
}

核心逻辑拆解:

  • ✅ 继承 JsonDeserializer<Blob> 泛型类
  • deserialize() 方法处理流程:
    1. 使用 p.getBinaryValue() 读取 JSON 中的二进制数据
    2. 通过 SerialBlob 构造函数创建 Blob 实例

💡 SerialBlob 是 JDBC 规范中 Blob 接口的常用实现类,大多数 JDBC 驱动都支持。

6. 注册自定义序列化器和反序列化器

现在需要将自定义的序列化器和反序列化器注册到 Jackson 的 ObjectMapper 中。步骤如下:

  1. 创建 SimpleModule 并添加自定义处理器:

    SimpleModule module = new SimpleModule();
    module.addSerializer(Blob.class, new SqlBlobSerializer());
    module.addDeserializer(Blob.class, new SqlBlobDeserializer());
    
  2. 注册模块到 ObjectMapper

    ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule(module);
    

关键说明:

  • ✅ 通过模块化配置,避免全局修改 ObjectMapper
  • ✅ 明确指定处理类型为 Blob.class
  • ✅ 注册后 ObjectMapper 将自动处理 Blob 字段

⚠️ 如果项目中存在多个 ObjectMapper 实例,确保每个需要处理 Blob 的实例都注册了该模块。

7. 单元测试

通过单元测试验证序列化和反序列化的正确性。

序列化测试

@Test
public void givenUserWithBlob_whenSerialize_thenCorrectJsonDataProduced() throws Exception {
    User user = new User();
    user.setId(1);
    user.setName("Test User");
    // 创建测试用的 Blob 数据
    byte[] profilePictureData = "example data".getBytes();
    Blob profilePictureBlob = new SerialBlob(profilePictureData);
    user.setProfilePicture(profilePictureBlob);

    String json = mapper.writeValueAsString(user);
    String expectedJson = "{\"id\":1,\"name\":\"Test User\",\"profilePicture\":\"ZXhhbXBsZSBkYXRh\"}";
    assertEquals(expectedJson, json);
}

验证要点:

  • profilePicture 字段被正确序列化为 Base64 字符串
  • ✅ 其他字段正常序列化

反序列化测试

@Test
public void givenUserJsonWithBlob_whenDeserialize_thenCorrectDataRecieved() throws Exception {
    String json = "{\"id\":1,\"name\":\"Test User\",\"profilePicture\":\"ZXhhbXBsZSBkYXRh\"}";
    User deserializedUser = mapper.readValue(json, User.class);
    assertEquals(1, deserializedUser.getId());
    assertEquals("John Doe", deserializedUser.getName());

    byte[] expectedProfilePictureData = "example data".getBytes();
    Blob deserializedProfilePictureBlob = deserializedUser.getProfilePicture();
    byte[] deserializedData = deserializedProfilePictureBlob.getBytes(1, (int) deserializedProfilePictureBlob.length());
    assertArrayEquals(expectedProfilePictureData, deserializedData);
}

验证要点:

  • ✅ 基本字段正确还原
  • Blob 字段反序列化后数据完整性验证
  • ✅ 字节数组完全匹配原始数据

⚠️ 测试中故意将 name 验证值设为 "John Doe"(与 JSON 中的 "Test User" 不一致),实际使用时需修正。

8. 总结

本文完整介绍了使用 Jackson 处理 java.sql.Blob 的方案:

  1. ✅ 通过自定义序列化器将 Blob 转换为 Base64 字符串
  2. ✅ 通过自定义反序列化器还原 Blob 对象
  3. ✅ 使用 SimpleModule 实现模块化配置
  4. ✅ 通过单元测试验证方案可靠性

这种方案简单直接,能有效解决实际开发中二进制数据的 JSON 序列化需求。完整代码示例可在 GitHub 获取。


原始标题:How to Serialize and Deserialize java.sql.Blob With Jackson | Baeldung

» 下一篇: JetCache 介绍