在开发过程中,遇到一个鬼畜的问题,在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. 浏览器-同源政策(same-origin policy)

    浏览器安全的基石是“同源政策”(same-origin policy). 1995年,同源政策由 Netscape 公司引入浏览器.目前,所有浏览器都实行这个政策. 何为同源? 协议相同 域名相同 端 ...

  2. 同步关键词synchronized

    概述 synchronized是java中的一个关键字,也就是说是Java语言内置的特性. synchronized( 一个任意的对象(锁) ){代码块中放操作共享数据的代码. } public sy ...

  3. learning java FileReader

    import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import ...

  4. chsh

    修改shell进程

  5. 括号匹配(POJ2955)题解

    原题地址:http://poj.org/problem?id=2955 题目大意:给出一串括号,求其中的最大匹配数. 我这么一说题目大意估计很多人就蒙了,其实我看到最开始的时候也是很蒙的.这里就来解释 ...

  6. 计蒜客 39268.Tasks-签到 (The 2019 ACM-ICPC China Shannxi Provincial Programming Contest A.) 2019ICPC西安邀请赛现场赛重现赛

    Tasks It's too late now, but you still have too much work to do. There are nn tasks on your list. Th ...

  7. 在windows环境下可以裁剪.jpg格式的图片

    发现在windows操作系统下,可以利用图片编辑器裁剪.jpg格式的尺寸大小.其四方有四个推子.可以移动.注意点击右方的“确定”按钮.

  8. CFD-Post中截取任意面的数据

    源视频下载链接: https://pan.baidu.com/s/1i4PtgDR 密码: wsn5

  9. 关于Java正则和转义中\\和\\\\的理解

    定义 一个转义字符的目的是开始一个字符序列,使得转义字符开头的该字符序列具有不同于该字符序列单独出现时的语义. 转义就是指转换该字符的原本意义,从而变成另外的意义. \作为Java的转义字符 1.在j ...

  10. Linux系统(ubuntu)部署Asp.Net Core网站

    一.前言 亲自动手尝试部署.Net Core在Linux,看了不少文章,感觉是很简单,但是做下去也会有很多问题,今天就写个文章记录下来. 二.环境安装 虚拟机(VMware),在网上找就行. 地址:h ...