ProtoStuff無法反序列化Deprecated註解成員問題記錄
在開發過程中,遇到一個鬼畜的問題,在DO的某個成員上新增@Deprecated
註解之後,通過ProtoStuff反序列化得到的DO中,這個成員一直為null;花了不少時間才定位這個問題,特此記錄一下
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",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,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);
System.out.println(fooParsed);
}
複製程式碼
測試結果如下,反序列化的例項中有相應的資料了
4. 小結
遵循ProtoStuff的使用規範,如果一個成員上有註解@Deprecated
,那麼這個成員的資料將不會被序列化和反序列化
II. 其他
1. 一灰灰Blog: liuyueyi.github.io/hexblog
一灰灰的個人部落格,記錄所有學習和工作中的博文,歡迎大家前去逛逛
2. 宣告
盡信書則不如,已上內容,純屬一家之言,因個人能力有限,難免有疏漏和錯誤之處,如發現bug或者有更好的建議,歡迎批評指正,不吝感激
- 微博地址: 小灰灰Blog
- QQ: 一灰灰/3302797840
3. 掃描關注
一灰灰blog