如何使用 Jackson 序列化和反序列化 java.sql.Blob
一、簡介
在本文中,我們將了解如何使用 Jackson 序列化和反序列化java.sql.Blob 。 java.sql.Blob代表Java中的二進位大物件(Blob),它可以儲存大量的二進位資料。使用 Jackson 處理 JSON 序列化和反序列化時,處理Blob物件可能會很棘手,因為 Jackson 不直接支援它們。但是,我們可以建立自訂序列化器和反序列化器來處理Blob物件。
我們將從設定環境和一個簡單的範例開始。接下來,我們將快速展示如何實作自訂序列化程式並針對Blob資料類型進行反序列化。最後,我們將使用簡單的範例用例透過測試來驗證我們的方法。
2. 依賴關係和範例設置
首先,確保我們的pom.xml中有必要的[jackson-databind](https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind)依賴項:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.3</version>
</dependency>
接下來我們將示範如何將Blob欄位整合到典型的 POJO 中,強調自訂序列化和反序列化的需求。讓我們建立一個簡單的User POJO,其中包含ID 、 name和Blob:類型的profilePicture :
public class User {
private int id;
private String name;
private Blob profilePicture;
//Constructor
// Getters and setters
}
稍後我們將使用此User類別來示範涉及Blob欄位的自訂序列化和反序列化。
3. 定義Blob序列化器
讓我們定義一個序列化器,它將User的profilePicture屬性轉換為 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 i表明此類是 Jackson 可以使用的序列化器的標準實作。它是一個標記註釋,通常用於 Jackson 中的內建序列化器和反序列化器。
我們的SqlBlobSerializer擴展了JsonSerialzier<Blob> ,這是 Jackson 提供的用於定義自訂序列化器的通用類別。我們重寫傳遞要序列化的Blob物件的序列化方法以及JsonGenerator and SerializerProvider. JsonGenerator用於產生結果 JSON 內容,而SerializerProvider用於提供用於序列化物件的序列化器
本質上, serialize方法使用getBytes().將Blob轉換為位元組數組。然後使用gen.writeBinary()將位元組數組寫入 Base64 編碼的二進位字串
5. 定義Blob反序列化器
現在讓我們定義一個反序列化器,它可以使用 Jackson 將 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);
}
}
}
在這裡, SqlBlobDeserializer擴展了JsonDeserializer<Blob> ,這是 Jackson 提供的用於定義自訂反序列化器的通用類別。然後,我們透過JsonParser重寫JsonDeserializer中的反序列化方法,JsonParser 是用來讀取 JSON 內容的解析器.此外,我們也傳遞DeserializationContext ,可用於存取有關反序列化過程的資訊。
本質上, SqlBlobDeserializer使用getBinaryValue()將二進位資料從 JSON 檢索到byte[] 。**然後,它將位元組數組轉換為SerialBlob object ,該物件是java.sql.Blob.**
6. 註冊自訂序列化器和反序列化器
現在我們有了BlobSerializer和BlobDeserializer ,下一步是將它們註冊到 Jackson。向 Jackson 註冊自訂序列化器和反序列化器意味著將 Jackson ObjectMapper配置為使用特定類別來將某些類型的 Java 物件與 JSON 相互轉換。 接下來讓我們建立一個SimpleModule並將blobSerializer和blobDeserializer加入到這個模組中:
SimpleModule module = new SimpleModule();
module.addSerializer(Blob.class, new SqlBlobSerializer());
module.addDeserializer(Blob.class, new SqlBlobDeserializer());
接下來,讓我們建立一個ObjectMapper ,並向其註冊該模組:
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(module);
本質上,透過向 ObjectMapper 註冊特定模組,我們確保它知道如何在 JSON 處理過程中處理非標準類型。在本例中,我們確保ObjectMapper知道如何使用自訂序列化器和反序列化器處理Blob類型。
7. 單元測試
最後,讓我們透過編寫一些單元測試來看看我們註冊的序列化器和反序列化器的運作情況。讓我們先測試BlobSerializer :
@Test
public void givenUserWithBlob_whenSerialize_thenCorrectJsonDataProduced() throws Exception {
User user = new User();
user.setId(1);
user.setName("Test User");
//sample blob data from byte[]
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);
}
此測試驗證序列化的 JSON 字串是否與預期的 JSON 格式相符。具體來說,JSON 中的profilePicture欄位應為表示Blob資料的 Base64 編碼字串。
接下來,讓我們為BlobDeserializer:
@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資料應與字串“example data”的原始位元組資料相符。此測試可確保自訂SqlBlobDeserialiser正確地將 base64 編碼的字串轉換回Blob對象,從而保留User物件中的原始二進位資料。
八、結論
在本文中,我們示範如何使用 Java 中的 Jackson 函式庫有效地序列化和反序列化java.sql.Blob物件。我們創建了自訂序列化器和反序列化器來處理Blob物件中的二進位數據,將它們與 JSON 格式的 Base64 編碼字串相互轉換。
與往常一樣,本文的完整實作可以在 GitHub 上找到。