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

目录
  • 引言
  • 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的资料请关注我们其它相关文章!

(0)

相关推荐

  • Java Kryo,Protostuff,Hessian序列化方式对比

    目录 前言 性能对比 前期准备 序列化后字节所占空间大小比较 其他比较 小结 前言 前段时间在写RPC框架的时候用到了Kryo.Hessian.Protostuff三种序列化方式.但是当时因为急于实现功能,就只是简单的的看了一下如何使用这三种序列化方式,并没有去深入研究各自的特性,以及优点和缺点.知道现在就将RPC框架写完了之后,才有时间静下心来对三种方式做一个对比,总结. Kryo.Hessain.Protostuff都是第三方开源的序列化/反序列化框架,要了解其各自的特性,我们首先需要知道序

  • BigDecimal divide除法除不尽报错的问题及解决

    目录 BigDecimal divide除法除不尽报错 解决办法 关于BigDecimal除法问题 BigDecimal做除法时 BigDecimal源码 BigDecimal divide除法除不尽报错 用BigDecimal做除法的时候,直接拿起两数怼上除法有时候会出现除不尽就会报错 列如: BigDecimal a = new BigDecimal(10); BigDecimal re = a.divide(new BigDecimal(3)); System.out.println(re

  • 使用BigDecimal除法后保留两位小数

    目录 BigDecimal除法后保留两位小数 详细描述 BigDecimal除法异常Non-terminating decimal expansion 异常分析 解决措施 思考 总结 BigDecimal除法后保留两位小数 BigDecimal numBigDecimal=new BigDecimal(5.33); numBigDecimal=ConvertNumber(numBigDecimal,3,2);//调用,5.33/3后保留两位小数1.7766666=1.78 //BigDecima

  • SpringBoot解决BigDecimal传到前端后精度丢失问题

    目录 简介 问题描述 实例 问题复现 Java后端BigDecimal的范围 解决方案 方案1:全局处理 方案2:局部处理 简介 本文用示例介绍SpringBoot如何解决BigDecimal传到前端后精度丢失问题. 问题描述 实例 Controller package com.knife.controller; import com.knife.entity.UserVO; import org.springframework.web.bind.annotation.GetMapping; i

  • Protostuff序列化和反序列化的使用说明

    大家都知道protobuf好用,可是在网上找到的netty整合protobuf的文章都是千篇一律,自己编写proto文件然后使用工具转java文件用起来复杂麻烦,经过不懈努力终于找到了一个简单的方法希望大家喜欢. google原生的protobuffer使用起来相当麻烦,首先要写.proto文件,然后编译.proto文件,生成对应的.java文件,鄙人试了一次,发现真的很麻烦.而protostuff的官方网站(http://www.protostuff.io/documentation/runt

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

    目录 引言 1. 场景复现 2. 疑似原因与兼容方法 引言 平时使用ProtoStuff作为序列化工具,对于一些POJO对象序列化,但是在实际使用中,发现针对BigDecimal对象进行序列化时却出现了问题 不管什么数,生成的byte数组都一样 无法正确反序列化 下面记录一下这个问题 1. 场景复现 我们使用的protostuff依赖如下 <dependency> <groupId>com.dyuproject.protostuff</groupId> <arti

  • Java基础之序列化与反序列化详解

    目录 1.什么是序列化与反序列化? 2.Java如何实现序列化和反序列化? 3.如何自定义序列化和反序列化呢? 4.writeObject和readObject方法 5.serializable接口 1.什么是序列化与反序列化? 序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程.一般将一个对象存储至一个储存媒介,例如档案或是记亿体缓冲等.在网络传输过程中,可以是字节或是XML等格式.而字节的或XML编码格式可以还原完全相等的对象.这个相反的过程又称为反序列

  • Python文件的应用之序列化与反序列化详解

    目录 初识序列化与反序列化 什么是序列化? 可序列化的数据类型 Python 中的json dumps() 与 loads() 函数 可序列化数据类型演示案例 bool .None 类型的序列化与反序列化 Python 中的pickle dumps() 与 loads() 函数 pickle模块的序列化与反序列化练习 json 模块 - 序列化小实战 前面章节我们学些了文件对象的创建.写入与读取,并且针对 .py 文件 与 .txt 文件进行了有针对性的小练习. 通过前面的学习我们知道,文件对象

  • Java中对象序列化与反序列化详解

    本文实例讲述了Java中对象序列化与反序列化.分享给大家供大家参考.具体如下: 一.简介 对象序列化(Serializable)是指将对象转换为字节序列的过程,而反序列化则是根据字节序列恢复对象的过程. 序列化一般用于以下场景: 1.永久性保存对象,保存对象的字节序列到本地文件中: 2.通过序列化对象在网络中传递对象: 3.通过序列化在进程间传递对象. 对象所属的类必须实现Serializable或是Externalizable接口才能被序列化.对实现了Serializable接口的类,其序列化

  • Java对象的序列化与反序列化详解

    一.序列化和反序列化的概念 把对象转换为字节序列的过程称为对象的序列化,把字节序列恢复为对象的过程称为对象的反序列化. 对象的序列化主要有两种途径: Ⅰ . 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中 Ⅱ.  在网络上传送对象的字节序列. 当两个进程在进行远程通信时,彼此可以发送各种类型的数据.无论是何种类型的数据,都会以二进制序列的形式在网络上传送.发送方需要把这个Java对象转换为字节序列,才能在网络上传送:接收方则需要把字节序列再恢复为Java对象. 二.序列化API 1.

  • .Net中的序列化和反序列化详解

    序列化和反序列化相信大家都经常听到,也都会用, 然而有些人可能不知道:.net为什么要有这个东西以及.net Frameword如何为我们实现这样的机制, 在这里我也是简单谈谈我对序列化和反序列化的一些理解. 一.什么序列化和反序列化 序列化通俗地讲就是将一个对象转换成一个字节流的过程,这样就可以轻松保存在磁盘文件或数据库中.反序列化是序列化的逆过程,就是将一个字节流转换回原来的对象的过程. 然而为什么需要序列化和反序列化这样的机制呢?这个问题也就涉及到序列化和反序列化的用途了, 对于序列化的主

  • Java IO之序列化与反序列化详解

    目录 1.什么是序列化与反序列化? 2.为什么要做序列化? 3.Java 怎么进行序列化? 总结 1.什么是序列化与反序列化? 序列化:指把堆内存中的 Java 对象数据,通过某种方式把对象存储到磁盘文件中或者传递给其他网络节点(在网络上传输).这个过程称为序列化.通俗来说就是将数据结构或对象转换成二进制串的过程 反序列化:把磁盘文件中的对象数据或者把网络节点上的对象数据,恢复成Java对象模型的过程.也就是将在序列化过程中所生成的二进制串转换成数据结构或者对象的过程 2.为什么要做序列化? ①

  • php中序列化与反序列化详解

    把复杂的数据类型压缩到一个字符串中 serialize() 把变量和它们的值编码成文本形式 unserialize() 恢复原先变量 eg: $stooges = array('Moe','Larry','Curly'); $new = serialize($stooges); print_r($new);echo "<br />"; print_r(unserialize($new)); 结果:a:3:{i:0;s:3:"Moe";i:1;s:5:&q

  • php数据序列化测试实例详解

    php数据序列化测试实例详解 测试代码 $msg = ['test'=>23]; $start = microtime(true); for($i=0;$i<100000;$i++){ $packMsg = msgpack_pack($msg); } echo 'pack len:'.strlen($packMsg)."\r\n"; $end = microtime(true); echo 'run time:'.($end-$start).'s'."\r\n&q

  • Java中BigDecimal类的使用详解

    不论是float 还是double都是浮点数,而计算机是二进制的,浮点数会失去一定的精确度.Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算.BigDecimal所创建的是对象,我们不能使用传统的+.-.*./等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法.方法中的参数也必须是BigDecimal的对象.构造器是类的特殊方法,专门用来创建对象,特别是带有参数的对象. 一.BigDecimal转换取Double数据 假设我

随机推荐