在开发过程中,遇到一个鬼畜的问题,在DO的某个成员上添加@Deprecated注解之后,通过ProtoStuff反序列化得到的DO中,这个成员一直为null;花了不少时间才定位这个问题,特此记录一下

原文 ProtoStuff无法反序列化Deprecated注解成员问题记录

I. 全程实录

1. 环境相关

原项目中使用protostuff作为POJO序列化工具,对应的版本为

<dependency>
<groupId>io.protostuff</groupId>
<artifactId>protostuff-runtime</artifactId>
<version>1.5.9</version>
</dependency>
<dependency>
<groupId>io.protostuff</groupId>
<artifactId>protostuff-core</artifactId>
<version>1.5.9</version>
</dependency>

2. 场景复现

写了一个简单的demo,我们在POJO中添加一个拥有删除注解的成员,然后查看下反序列化结果

@Data
@NoArgsConstructor
@AllArgsConstructor
public static class BDO implements Serializable {
private String a;
@Deprecated
private String b;
} @Test
public void testSer() {
BDO b = new BDO("10", "20");
Schema<BDO> schema = RuntimeSchema.getSchema(BDO.class); LinkedBuffer buffer = LinkedBuffer.allocate(512);
final byte[] protostuff;
try {
protostuff = ProtostuffIOUtil.toByteArray(b, schema, buffer);
} finally {
buffer.clear();
} // deser
BDO fooParsed = schema.newMessage();
ProtostuffIOUtil.mergeFrom(protostuff, fooParsed, schema);
System.out.println(fooParsed);
}

下面是测试输出,可以看到反序列化的结果中,b为null

自然就会有个疑问,是在序列化的时候直接丢掉了这个成员信息呢,还是反序列化的时候跳过了这个成员?

我们新增一个POJO,与BDO的成员类似,只是没有@Deprecated注解

@Data
@NoArgsConstructor
@AllArgsConstructor
public static class NDO implements Serializable {
private String a;
private String b;
}

然后验证下BDO序列化的结果,通过反序列化为NDO对象,如果b成员有值,说明在序列化的时候并没有丢掉;

@Test
public void testSer2() {
BDO b = new BDO("10", "20");
Schema<BDO> schema = RuntimeSchema.getSchema(BDO.class); LinkedBuffer buffer = LinkedBuffer.allocate(512);
final byte[] protostuff;
try {
protostuff = ProtostuffIOUtil.toByteArray(b, schema, buffer);
} finally {
buffer.clear();
} Schema<NDO> nSchema = RuntimeSchema.getSchema(NDO.class);
NDO ndo = nSchema.newMessage();
ProtostuffIOUtil.mergeFrom(protostuff, ndo, nSchema);
System.out.println(ndo);
}

从下面的输出可以看到,反序列化不出来,在序列化的时候就已经丢掉了

接着我们再验证下NDO序列化的结果,因为没有Deprecated注解,反序列化为NDO对象时,应该是齐全的,那么反序列化为BDO呢

@Test
public void testSer3() {
NDO n = new NDO("10", "20");
Schema<NDO> schema = RuntimeSchema.getSchema(NDO.class); LinkedBuffer buffer = LinkedBuffer.allocate(512);
final byte[] protostuff;
try {
protostuff = ProtostuffIOUtil.toByteArray(n, schema, buffer);
} finally {
buffer.clear();
} NDO ans = schema.newMessage();
ProtostuffIOUtil.mergeFrom(protostuff, ans, schema);
System.out.println(ans); Schema<BDO> bSchema = RuntimeSchema.getSchema(BDO.class);
BDO bdo = bSchema.newMessage();
ProtostuffIOUtil.mergeFrom(protostuff, bdo, bSchema);
System.out.println(bdo);
}

从下面的输出可以看出,反序列化时,成员上有@Deprecated注解时,也无法获取正确的结果

3. 兼容方案

查了下protostuf的相关文档,个人感觉它的设计理念就是认为加了这个删除注解,就没有必要继续存在了,就直接给忽略了。那么我希望加上了这个注解的可以被序列化/反序列化,有办法么?

查看api的时候,发现在创建Schema的时候,有个方法io.protostuff.runtime.RuntimeSchema#createFrom(java.lang.Class<T>, java.util.Map<java.lang.String,java.lang.String>, io.protostuff.runtime.IdStrategy), 可以指定成员列表

于是我们就有了一个猥琐的兼容方式

@Test
public void testSer() {
BDO b = new BDO("10", "20");
Map<String, String> map = new HashMap<>();
map.put("a", "a");
map.put("b", "b");
Schema<BDO> schema = RuntimeSchema.createFrom(BDO.class, map, RuntimeEnv.ID_STRATEGY);
// Schema<BDO> schema = RuntimeSchema.createFrom(BDO.class, new String[]{}, RuntimeEnv.ID_STRATEGY); LinkedBuffer buffer = LinkedBuffer.allocate(512);
final byte[] protostuff;
try {
protostuff = ProtostuffIOUtil.toByteArray(b, schema, buffer);
} finally {
buffer.clear();
} // deser
BDO fooParsed = schema.newMessage();
ProtostuffIOUtil.mergeFrom(protostuff, fooParsed, schema);
System.out.println(fooParsed);
}

测试结果如下,反序列化的实例中有相应的数据了

4. 小结

遵循ProtoStuff的使用规范,如果一个成员上有注解@Deprecated,那么这个成员的数据将不会被序列化和反序列化

II. 其他

1. 一灰灰Bloghttps://liuyueyi.github.io/hexblog

一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛

2. 声明

尽信书则不如,已上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激

3. 扫描关注

一灰灰blog

知识星球

ProtoStuff无法反序列化Deprecated注解成员问题记录的更多相关文章

  1. @Deprecated注解

    它的作用是对不应该再使用的方法添加注解,当编程人员使用这些方法时,将会在编译时显示提示信息,它与javadoc里的@deprecated标记有相同的功能,准确的说,它还不如javadoc @depre ...

  2. @Deprecated注解功能

    @Deprecated注解功能 标记不建议使用的方法,但是仍然可以用 当方法有更好的方法替换时,但是此方法还有使用时可以使用该注解

  3. Spring aop+自定义注解统一记录用户行为日志

    写在前面 本文不涉及过多的Spring aop基本概念以及基本用法介绍,以实际场景使用为主. 场景 我们通常有这样一个需求:打印后台接口请求的具体参数,打印接口请求的最终响应结果,以及记录哪个用户在什 ...

  4. java protostuff 序列化反序列化工具

    protostuff是由谷歌开发的一个非常优秀的序列化反序列化工具 maven导入包: <dependency> <groupId>io.protostuff</grou ...

  5. java注解日志记录到数据库

    1. pom添加依赖包 <!--添加aop依赖--><dependency> <groupId>org.springframework.boot</group ...

  6. spring注解简单记录

    @Autowired 自动匹配,按类型 @qualifiter("beanname") 当有多个bean匹配时,可指定bean名称 @Resource byname优先匹配,然后b ...

  7. Servlet3.0使用@WebServlet注解配置问题记录

    文档说@WebServlet的配置属性都是可选的,不是必需的. 经实践,将一个Servlet配置成load-on-startup的Servlet时,若只添加loadOnStartup属性,该Servl ...

  8. 初学java注解编程 记录错误及解决办法

    1 :在form表单提交到controller层时 利用hbim的封装的访问数据库 form表单中属性要加上method方法 不然不成功. 2 :在运行eclipse时 有时粘贴个数据或者删除个字段老 ...

  9. 160919、使用AOP与注解记录Java日志

    有些时候,我想要把每个运行过的方法接收到的参数.返回值和执行时间等信息记录(通过slf4j 和 log4j)下来.在AspectJ.jcabi-aspects和Java注解的帮助下我实现了这个想法. ...

随机推荐

  1. 吉首大学2019年程序设计竞赛(重现赛)D - 数列求和(嘤雄难度)

    链接:https://ac.nowcoder.com/acm/contest/992/D $a_{i}=\dfrac {3a_{i-1}-a_{i-2}}{2}+i+1$ 移项再化一下 $a_{i}- ...

  2. k8s 基础概念

    摘录自k8s中文社区https://www.kubernetes.org.cn/course kubernetes 源自希腊文,意为舵手,k与s之间是8个字母,所以也叫k8s, docker就像一个个 ...

  3. 洛谷 题解 P2731 【骑马修栅栏 Riding the Fences】

    简单的开始 完美の开始 这里数组什么的用来干什么后面标注的清楚了 #include<iostream> #include<cstdio> #include<cmath&g ...

  4. 1.typescirpt学习之路,*.d.ts和@types关系理解

    今天看了看ts,文档上很多没用讲,小编疑惑了很久一个问题! *.d.ts和@types啥关系,小编查阅了很多文档,才弄明白. 首先,@types是npm的一个分支,我们把npm包发上去,npm包就会托 ...

  5. beforeDestroy的使用

    beforeDestroy ---实例销毁之前调用 需求是这样的: important:下面截图数据都是测试数据 日期在我点击查询的时候要存储,刷新就读内存,但是我点击其他页面再进来的时候,这个内存要 ...

  6. koa post提交数据,koa-bodyparser中间件来获取post提交数据

    原生 Nodejs 获取 post 提交数据 首先创建并初始化一个node应用,根路由使用index.ejs模板 var Koa=require('koa') var router = require ...

  7. ckplayer去掉/修改右上角logo(位置)

    ckplayer.js中搜索:logo(ckplayer.xml中搜索<logo>) 1:去掉的方法是修改成logo:'null'(ckplayer.xml中修改成<logo> ...

  8. 剑指offer:平衡二叉树

    题目描述: 输入一棵二叉树,判断该二叉树是否是平衡二叉树. 思路分析: 首先要明确平衡二叉树的定义.平衡二叉是左右子树的高度差小于等于1,且左右子树都为平衡二叉树.这里就存在一个递归判断左右子树是否为 ...

  9. Python plot_surface(Axes3D)方法:绘制3D图形

    3D 图形需要的数据与等高线图基本相同:X.Y 数据决定坐标点,Z 轴数据决定 X.Y 坐标点对应的高度.与等高线图使用等高线来代表高度不同,3D 图形将会以更直观的形式来表示高度. 为了绘制 3D ...

  10. jmeter 内存溢出原因及解决方法

    jmeter是一个java开发的开源性能测试工具,在性能测试中可支持模拟并发压测,但有时候当模拟并发请求较大或者脚本运行时间较长时,压力机会出现卡顿甚至报异常————内存溢出, 这里就介绍下如何解决内 ...