在開發過程當中,遇到一個鬼畜的問題,在DO的某個成員上添加@Deprecated
註解以後,經過ProtoStuff反序列化獲得的DO中,這個成員一直爲null;花了很多時間才定位這個問題,特此記錄一下java
原文 ProtoStuff沒法反序列化Deprecated註解成員問題記錄
原項目中使用protostuff做爲POJO序列化工具,對應的版本爲git
<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>
寫了一個簡單的demo,咱們在POJO中添加一個擁有刪除註解的成員,而後查看下反序列化結果github
@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爲nullapi
天然就會有個疑問,是在序列化的時候直接丟掉了這個成員信息呢,仍是反序列化的時候跳過了這個成員?工具
咱們新增一個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); }
從下面的輸出能夠看到,反序列化不出來,在序列化的時候就已經丟掉了ui
接着咱們再驗證下NDO序列化的結果,由於沒有Deprecated註解,反序列化爲NDO對象時,應該是齊全的,那麼反序列化爲BDO呢spa
@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
註解時,也沒法獲取正確的結果設計
查了下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); }
測試結果以下,反序列化的實例中有相應的數據了
遵循ProtoStuff的使用規範,若是一個成員上有註解@Deprecated
,那麼這個成員的數據將不會被序列化和反序列化
一灰灰的我的博客,記錄全部學習和工做中的博文,歡迎你們前去逛逛
盡信書則不如,已上內容,純屬一家之言,因我的能力有限,不免有疏漏和錯誤之處,如發現bug或者有更好的建議,歡迎批評指正,不吝感激
一灰灰blog
知識星球