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

 更新时间:2022年08月20日 09:33:44   作者:一灰灰  
这篇文章主要为大家介绍了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的资料请关注脚本之家其它相关文章!

相关文章

  • MyBatis通过JDBC数据驱动生成的执行语句问题

    MyBatis通过JDBC数据驱动生成的执行语句问题

    这篇文章主要介绍了MyBatis通过JDBC数据驱动生成的执行语句问题的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2016-08-08
  • Java中基于DeferredResult的异步服务详解

    Java中基于DeferredResult的异步服务详解

    这篇文章主要介绍了Java中基于DeferredResult的异步服务详解,DeferredResult字面意思是"延迟结果",它允许Spring MVC收到请求后,立即释放(归还)容器线程,以便容器可以接收更多的外部请求,提升吞吐量,需要的朋友可以参考下
    2023-12-12
  • 深入了解java中的string对象

    深入了解java中的string对象

    这篇文章主要介绍了java中的string对象,String对象是Java中使用最频繁的对象之一,所以Java开发者们也在不断地对String对象的实现进行优化,以便提升String对象的性能。对此感兴趣的朋友跟随小编一起看看吧
    2019-11-11
  • 解析Java的InputStream类并借助其读取ppt文件

    解析Java的InputStream类并借助其读取ppt文件

    这篇文章主要介绍了Java的InputStream类并借助其读取ppt文件,讲到了InputStream类中一些常用的方法的问题,需要的朋友可以参考下
    2015-11-11
  • 解决FileWriter 写入文本不换行的问题

    解决FileWriter 写入文本不换行的问题

    这篇文章主要介绍了解决FileWriter 写入文本不换行的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • 一文讲通Java为什么不支持多继承原理

    一文讲通Java为什么不支持多继承原理

    这篇文章主要为大家介绍了java为什么不支持多继承原理详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03
  • java获取json中的全部键值对实例

    java获取json中的全部键值对实例

    下面小编就为大家分享一篇java获取json中的全部键值对实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-03-03
  • Java file类中renameTo方法操作实例

    Java file类中renameTo方法操作实例

    renameTo()方法是File类的一部分,renameTo()函数用于将文件的抽象路径名重命名为给定的路径名​​,下面这篇文章主要给大家介绍了关于Java file类中renameTo方法操作的相关资料,需要的朋友可以参考下
    2022-11-11
  • Java实现断点下载功能的示例代码

    Java实现断点下载功能的示例代码

    当下载一个很大的文件时,如果下载到一半暂停,如果继续下载呢?断点下载就是解决这个问题的。本文将用Java语言实现断点下载,需要的可以参考一下
    2022-05-05
  • Java中Map和Set练习项目实例代码

    Java中Map和Set练习项目实例代码

    这篇文章主要给大家介绍了关于Java中Map和Set练习项目的相关资料,首先介绍了如何使用map来统计字符串数组中每个字符串的出现次数,然后讨论了如何使用set来找出只出现一次的数字,最后提出了一个解决坏键盘打字问题的思路,需要的朋友可以参考下
    2024-11-11

最新评论