Reputation: 11016
I have a class of this form:
public class Foo implements Serializable {
private static final long serialVersionUID = 20130605L;
private Object fields[];
// Methods, etc.
}
For some time this was ok, but now (for readability and maintenance) have been transformed to:
public class Foo implements Serializable {
private static final long serialVersionUID = 20130605L;
private String field1;
private String field2;
private Boolean fiedl3;
// Methods, etc.
}
And the problem come when you tray to read old files with the new class version. If you use different serialVersionUID, aren't compatible. If you use the same serialVersionUID, I need to implement something to make it compatible. And this is my aproach, overwrite private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException
so I can check manually what version is the object in the file.
The problem again come in that I want to use java.io.ObjectInputStream.defaultReadObject();
so it automatically do its "magic" for next versions (in witch new fields will be optional). So I have something like:
public class Foo implements Serializable {
private static final long serialVersionUID = 20130605L;
private String field1;
private String field2;
private Boolean fiedl3;
// Methods, etc.
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
Object obj = in.readObject();
if (obj instanceof Object[]) {
Object[] tmp = (Object[])obj;
field1 = (String)obj[0];
field2 = (String)obj[1];
// ....
} else {
in.defaultReadObject();
}
}
}
And the problem is that as I have already read part of the stream, the defaultReadObject method crash.
I have search for a Stream that let you read an object twice, but I don't found it. I also know that I can make the read totally manually, but then each time I add another field I will need to modify this (in defaultReadObject
, as it write fields name, it can restore only the field that were read automatically).
So my question is ¿How can I make it?
Note: I only need that compatibility is for read old class object from new class and new class object from new class object. Also I have read other question but they only answer how to plan a good class to have backguard compatibility (I should have read it before :-( ).
Upvotes: 0
Views: 530
Reputation: 11016
The only solution that I have found is to maintain a reference to the old field. Note that you can set it as transient
because then it will not be read, so you must carry it for ever.
public class Foo implements Serializable {
private static final long serialVersionUID = 20130605L;
private Object fields[]; // So we can read it in old saved version.
private String field1;
private String field2;
private Boolean fiedl3;
// Methods, etc.
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
if (fields != null) {
// If we have read an old version.
field1 = (String)fields[0];
field2 = (String)fields[1];
field3 = (Boolean)fields[2];
// ....
// We set fields to null so no more space is waste than necessary.
fields = null;
}
}
}
Upvotes: 1