ProtoStuff不支持BigDecimal序列化及反序列化詳解
引言
平時使用ProtoStuff作為序列化工具,對于一些POJO對象序列化,但是在實際使用中,發(fā)現(xiàn)針對BigDecimal對象進行序列化時卻出現(xiàn)了問題
- 不管什么數(shù),生成的byte數(shù)組都一樣
- 無法正確反序列化
下面記錄一下這個問題
1. 場景復現(xiàn)
我們使用的protostuff依賴如下
<dependency>
<groupId>com.dyuproject.protostuff</groupId>
<artifactId>protostuff-core</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>com.dyuproject.protostuff</groupId>
<artifactId>protostuff-runtime</artifactId>
<version>1.1.3</version>
</dependency>
寫一個簡單測試demo,如下
public static byte[] serialize(Object obj) {
Schema schema = RuntimeSchema.getSchema(obj.getClass());
LinkedBuffer buffer = LinkedBuffer.allocate(1048576);
byte[] protoStuff;
try {
protoStuff = ProtostuffIOUtil.toByteArray(obj, schema, buffer);
} catch (Exception var8) {
throw new RuntimeException("Failed to serializer");
} finally {
buffer.clear();
}
return protoStuff;
}
public static <T> T deserialize(byte[] paramArrayOfByte, Class<T> targetClass) {
if (paramArrayOfByte != null && paramArrayOfByte.length != 0) {
Schema<T> schema = RuntimeSchema.getSchema(targetClass);
T instance = schema.newMessage();
ProtostuffIOUtil.mergeFrom(paramArrayOfByte, instance, schema);
return instance;
} else {
throw new RuntimeException("Failed to deserialize");
}
}
@Test
public void testSer() {
byte[] ans = serialize(new BigDecimal(20));
byte[] ans2 = serialize(new BigDecimal(120));
System.out.println(new String(ans));
System.out.println(new String(ans2));
BigDecimal res = deserialize(ans, BigDecimal.class);
System.out.println(res);
}
執(zhí)行如下

2. 疑似原因與兼容方法
并沒有找到具體的原因,在github上有一個issure: github.com/protostuff/…,其中回復為
Protostuff works on user-defined types (pojos), not on built-in jdk types.
上面的說法是ProtoStuff更多的是用于簡單對象的序列化,而不是基礎的jdk類型,因此推薦的是序列一個成員變量為BigDecimal的對象
接下來我們試一下,定義一個簡單的對象,成員為BigDecimal的場景
@Data
public static class InnerDecimal {
private BigDecimal decimal;
public InnerDecimal() {
}
public InnerDecimal(BigDecimal decimal) {
this.decimal = decimal;
}
}
@Test
public void testSer() {
byte[] ans = serialize(new InnerDecimal(new BigDecimal(20.123)));
byte[] ans2 = serialize(new InnerDecimal(new BigDecimal(120.1970824)));
System.out.println(new String(ans));
System.out.println(new String(ans2));
InnerDecimal res = deserialize(ans, InnerDecimal.class);
System.out.println(res);
}
測試輸出如下

上面雖然可以正常工作,但與我們希望的差別有點大,序列化一個BigDecimal,還需要定義一個POJO包裝他,有點麻煩;
于是一個猥瑣的方法就是在序列化和反序列化的時候,針對BigDeimal進行特殊處理
public static byte[] serialize(Object obj) {
if (obj instanceof BigDecimal) {
obj = ((BigDecimal) obj).toPlainString();
}
Schema schema = RuntimeSchema.getSchema(obj.getClass());
LinkedBuffer buffer = LinkedBuffer.allocate(1048576);
byte[] protoStuff;
try {
protoStuff = ProtostuffIOUtil.toByteArray(obj, schema, buffer);
} catch (Exception var8) {
throw new RuntimeException("Failed to serializer");
} finally {
buffer.clear();
}
return protoStuff;
}
public static <T> T deserialize(byte[] paramArrayOfByte, Class<T> targetClass) {
if (paramArrayOfByte != null && paramArrayOfByte.length != 0) {
Schema schema;
if (targetClass.isAssignableFrom(BigDecimal.class)) {
schema = RuntimeSchema.getSchema(String.class);
Object instance = schema.newMessage();
ProtostuffIOUtil.mergeFrom(paramArrayOfByte, instance, schema);
return (T) new BigDecimal((String) instance);
} else {
schema = RuntimeSchema.getSchema(targetClass);
Object instance = schema.newMessage();
ProtostuffIOUtil.mergeFrom(paramArrayOfByte, instance, schema);
return (T) instance;
}
} else {
throw new RuntimeException("Failed to deserialize");
}
}
再次測試,正常執(zhí)行

以上就是ProtoStuff不支持BigDecimal序列化及反序列化詳解的詳細內(nèi)容,更多關于ProtoStuff不支持BigDecimal的資料請關注腳本之家其它相關文章!
相關文章
Java微信公眾平臺開發(fā)(10) 微信自定義菜單的創(chuàng)建實現(xiàn)
這篇文章主要為大家詳細介紹了Java微信公眾平臺開發(fā)第十步,微信自定義菜單的創(chuàng)建實現(xiàn),具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-04-04
springboot之redis cache TTL選項的使用
這篇文章主要介紹了springboot之redis cache TTL選項的使用方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07
java.lang.ArrayIndexOutOfBoundsException數(shù)組越界異常問題解決
這篇文章主要給大家介紹了關于java.lang.ArrayIndexOutOfBoundsException數(shù)組越界異常問題解決的相關資料,數(shù)組越界訪問是一個非常嚴重的問題,文中通過圖文將解決的辦法介紹的非常詳細,需要的朋友可以參考下2024-01-01
spring boot中interceptor攔截器未生效的解決
這篇文章主要介紹了spring boot中interceptor攔截器未生效的解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09

