<
>

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

2022-08-20 12:52:54 来源:易采站长站 作者:

目录
引言1. 场景复现2. 疑似原因与兼容方法

引言

平时使用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的资料请关注易采站长站其它相关文章!

暂时禁止评论

微信扫一扫

易采站长站微信账号