软件编程
位置:首页>> 软件编程>> java编程>> ProtoStuff不支持BigDecimal序列化及反序列化详解

ProtoStuff不支持BigDecimal序列化及反序列化详解

作者:一灰灰  发布时间:2022-09-19 06:53:30 

标签: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);
}

执行如下

ProtoStuff不支持BigDecimal序列化及反序列化详解

2. 疑似原因与兼容方法

并没有找到具体的原因,在github上有一个issure: github.com/protostuff/&hellip;,其中回复为

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);
}

测试输出如下

ProtoStuff不支持BigDecimal序列化及反序列化详解

上面虽然可以正常工作,但与我们希望的差别有点大,序列化一个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序列化及反序列化详解

来源:https://juejin.cn/post/7133583979667521544

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com