ProtoStuff不支持BigDecimal序列化及反序列化詳解
引言
平時(shí)使用ProtoStuff作為序列化工具,對(duì)于一些POJO對(duì)象序列化,但是在實(shí)際使用中,發(fā)現(xiàn)針對(duì)BigDecimal對(duì)象進(jìn)行序列化時(shí)卻出現(xiàn)了問(wèn)題
- 不管什么數(shù),生成的byte數(shù)組都一樣
- 無(wú)法正確反序列化
下面記錄一下這個(gè)問(wèn)題
1. 場(chǎng)景復(fù)現(xiàn)
我們使用的protostuff依賴(lài)如下
<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>
寫(xiě)一個(gè)簡(jiǎn)單測(cè)試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. 疑似原因與兼容方法
并沒(méi)有找到具體的原因,在github上有一個(gè)issure: github.com/protostuff/…,其中回復(fù)為
Protostuff works on user-defined types (pojos), not on built-in jdk types.
上面的說(shuō)法是ProtoStuff更多的是用于簡(jiǎn)單對(duì)象的序列化,而不是基礎(chǔ)的jdk類(lèi)型,因此推薦的是序列一個(gè)成員變量為BigDecimal的對(duì)象
接下來(lái)我們?cè)囈幌?,定義一個(gè)簡(jiǎn)單的對(duì)象,成員為BigDecimal的場(chǎng)景
@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);
}
測(cè)試輸出如下

上面雖然可以正常工作,但與我們希望的差別有點(diǎn)大,序列化一個(gè)BigDecimal,還需要定義一個(gè)POJO包裝他,有點(diǎn)麻煩;
于是一個(gè)猥瑣的方法就是在序列化和反序列化的時(shí)候,針對(duì)BigDeimal進(jìn)行特殊處理
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");
}
}
再次測(cè)試,正常執(zhí)行

以上就是ProtoStuff不支持BigDecimal序列化及反序列化詳解的詳細(xì)內(nèi)容,更多關(guān)于ProtoStuff不支持BigDecimal的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
MyBatis通過(guò)JDBC數(shù)據(jù)驅(qū)動(dòng)生成的執(zhí)行語(yǔ)句問(wèn)題
這篇文章主要介紹了MyBatis通過(guò)JDBC數(shù)據(jù)驅(qū)動(dòng)生成的執(zhí)行語(yǔ)句問(wèn)題的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-08-08
Java中基于DeferredResult的異步服務(wù)詳解
這篇文章主要介紹了Java中基于DeferredResult的異步服務(wù)詳解,DeferredResult字面意思是"延遲結(jié)果",它允許Spring MVC收到請(qǐng)求后,立即釋放(歸還)容器線(xiàn)程,以便容器可以接收更多的外部請(qǐng)求,提升吞吐量,需要的朋友可以參考下2023-12-12
解析Java的InputStream類(lèi)并借助其讀取ppt文件
這篇文章主要介紹了Java的InputStream類(lèi)并借助其讀取ppt文件,講到了InputStream類(lèi)中一些常用的方法的問(wèn)題,需要的朋友可以參考下2015-11-11
解決FileWriter 寫(xiě)入文本不換行的問(wèn)題
這篇文章主要介紹了解決FileWriter 寫(xiě)入文本不換行的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07
Java?file類(lèi)中renameTo方法操作實(shí)例
renameTo()方法是File類(lèi)的一部分,renameTo()函數(shù)用于將文件的抽象路徑名重命名為給定的路徑名??,下面這篇文章主要給大家介紹了關(guān)于Java?file類(lèi)中renameTo方法操作的相關(guān)資料,需要的朋友可以參考下2022-11-11
Java實(shí)現(xiàn)斷點(diǎn)下載功能的示例代碼
當(dāng)下載一個(gè)很大的文件時(shí),如果下載到一半暫停,如果繼續(xù)下載呢?斷點(diǎn)下載就是解決這個(gè)問(wèn)題的。本文將用Java語(yǔ)言實(shí)現(xiàn)斷點(diǎn)下載,需要的可以參考一下2022-05-05
Java中Map和Set練習(xí)項(xiàng)目實(shí)例代碼
這篇文章主要給大家介紹了關(guān)于Java中Map和Set練習(xí)項(xiàng)目的相關(guān)資料,首先介紹了如何使用map來(lái)統(tǒng)計(jì)字符串?dāng)?shù)組中每個(gè)字符串的出現(xiàn)次數(shù),然后討論了如何使用set來(lái)找出只出現(xiàn)一次的數(shù)字,最后提出了一個(gè)解決壞鍵盤(pán)打字問(wèn)題的思路,需要的朋友可以參考下2024-11-11

