ProtoStuff不支持BigDecimal序列化及反序列化詳解
引言
平時使用ProtoStuff作為序列化工具,對於一些POJO對象序列化,但是在實際使用中,發現針對BigDecimal對象進行序列化時卻出現瞭問題
- 不管什麼數,生成的byte數組都一樣
- 無法正確反序列化
下面記錄一下這個問題
1. 場景復現
我們使用的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); }
執行如下
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"); } }
再次測試,正常執行
以上就是ProtoStuff不支持BigDecimal序列化及反序列化詳解的詳細內容,更多關於ProtoStuff不支持BigDecimal的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- Java Kryo,Protostuff,Hessian序列化方式對比
- BigDecimal的加減乘除計算方法詳解
- Java精確計算BigDecimal類詳解
- Java BigDecimal案例詳解
- JAVA biginteger類bigdecimal類的使用示例學習