[英]How to exclude field from class serialization in runtime?
如何在運行時從序列化過程中排除類字段? 編譯時有瞬態修飾符,但運行時呢? 我的意思是使用ObjectOutputStream的常見java序列化,而不是gson或其他東西。
對不起我想我沒解釋得對。 這是不完全有關序列化的,而是德 -serialization。 我有一批遺留文件並像這樣處理它們:
public class Deserialize {
/**
* @param args
* @throws IOException
* @throws ClassNotFoundException
*/
public static void main(String[] args) throws ClassNotFoundException, IOException {
File file = new File("/home/developer/workspace/DDFS/some.ddf");
HackedObjectInputStream in = new HackedObjectInputStream(new GZIPInputStream(new FileInputStream(file)));
System.out.println("Attempt to open " + file.getAbsolutePath());
Object obj = in.readObject();
in.close();
}
static class HackedObjectInputStream extends ObjectInputStream
{
/**
* Migration table. Holds old to new classes representation.
*/
private static final Map<String, Class<?>> MIGRATION_MAP = new HashMap<String, Class<?>>();
static
{
MIGRATION_MAP.put("DBOBExit", Exit.class);
}
/**
* Constructor.
* @param stream input stream
* @throws IOException if io error
*/
public HackedObjectInputStream(final InputStream stream) throws IOException
{
super(stream);
}
@Override
protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException
{
ObjectStreamClass resultClassDescriptor = super.readClassDescriptor();
for (final String oldName : MIGRATION_MAP.keySet())
{
if (resultClassDescriptor.getName().equals(oldName))
{
resultClassDescriptor = ObjectStreamClass.lookup(MIGRATION_MAP.get(oldName));
}
}
return resultClassDescriptor;
}
}
}
此代碼適用於大多數文件,但有些文件會拋出
Exception in thread "main" java.lang.ClassCastException: cannot assign instance of java.awt.Polygon to field Exit.msgbackPt of type java.awt.Point in instance of Exit
at java.io.ObjectStreamClass$FieldReflector.setObjFieldValues(ObjectStreamClass.java:2053)
因為Exit類的版本不同。 新版本有新字段。 向新字段添加瞬態時錯誤消失,但另一個文件開始拋出異常(最新文件)。
因此,如果我檢測到傳統的加強文件,我可以在運行時向這些新文件添加瞬態嗎? 也許反思或什么?
對象的默認序列化機制會寫入對象的類,類簽名以及所有非瞬態和非靜態字段的值。 對其他對象的引用(瞬態或靜態字段除外)也會導致寫入這些對象。
因此,當您將變量聲明為瞬態時,ObjectOutputStream應該忽略它。 確保使用transient
關鍵字而不是@Transient
注釋。 某些ORM框架使用此類注釋來標記不應保存在數據庫中的字段。 它們對於buildin序列化框架毫無意義。
private transient String foo; // Field gets ignored by ObjectOutputStream
@Transient private String bar; // Treated normally by ObjectOutputStream (might mean something for some other framework)
您可以使用transient
修飾符:
http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.3.1.3
特定類的序列化表示取決於類本身,您不能在外部更改它,您可以獲得的最接近的是定義具有自定義序列化行為的子類但僅影響該子類的對象,而不影響父類的對象類型。
如果您根本無法修改有問題的類,那么您唯一的選擇是繼承ObjectOutputStream並覆蓋replaceObject
以在寫入時將問題對象替換為僅包含您想要的數據的另一個問題對象,以及讀取時的鏡像處理過程time(子類ObjectInputStream和override resolveObject
)。
你在挖這個錯誤的洞。 您應該研究覆蓋readResolve()
,而不是弄亂運行時決定哪些字段要序列化並覆蓋readClassDescriptor()
readResolve()
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.