如何在运行时从序列化过程中排除类字段?
虽然在编译时有“transient”修饰符,但在运行时该怎么办?
我的意思是使用ObjectOutputStream进行常规Java序列化,而不是gson或其他内容。
抱歉,我想我没有解释清楚。这与序列化不完全相关,而与反序列化有关。我有一批旧文件,我像这样处理它们:
抱歉,我想我没有解释清楚。这与序列化不完全相关,而与反序列化有关。我有一批旧文件,我像这样处理它们:
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类有不同的版本,新版本有新的字段。 当我在新字段上添加“transient”关键字时,错误消失了,但另一个文件开始抛出异常(最近的文件)。
如果我检测到旧版序列化文件,我是否可以在运行时将这些新字段添加“transient”关键字呢? 也许使用反射或其他方法?
writeObject()
和readObject()
,或者使用Externalizable
替代Serializable
,这样可以完全控制整个过程:http://docs.oracle.com/javase/7/docs/platform/serialization/spec/serial-arch.html#4539(以及该规范的其他部分)。请注意,您可能需要正确地反序列化整个类,并在反序列化时处理确定哪些字段已在序列化期间编写的问题(通过在数据之前编写一堆标志或类似的东西)。 - millimoose