2

I have a list of objects serialized into a file:

class MyClass implements Serializable {

    public String location;
    public SomeClass lastUpdatedAt;

}

Unfortunately, I now have a new version of this class, and we don't have SomeClass anymore; The reason is complex but I need to serialize this back into this new form (this is an example class and not the actual class obviously):

class MyClass implements Serializable {

    public String location;

}

In short, I'd like to ignore a property at deserialization.

Please not that I cant change the original class source file. I only have the new source file

However ObjectInputStream fails when it tries to find the SomeClass on the classpath:

try {
    FileInputStream fis;
    ObjectInputStream is;
    File f = getSavedFile();
    if (f.exists()) {
        fis = new FileInputStream(f);
        is = new ObjectInputStream(fis);
        ArrayList<MyClass> result = (ArrayList<MyClass>) is.readObject(); //fails
        is.close();
        fis.close();
        }
    }
    catch (Exception e) {
        //ClassNotFound exception because SomeClass is not on the classpath.
        e.printStackTrace();

    }

I know you can extend ObjectInputStream and implement something there, but I'm not familiar with serialization that much and hope that someone solved the same problem.

breakline
  • 5,776
  • 8
  • 45
  • 84

3 Answers3

5
class MyClass implements Serializable {

    public String location;
    public transient SomeClass lastUpdatedAt;

}

Maybe you have success with that. If doesn't work then you have to override the method.

For this reason I don't like the automated serialization and I do manually: implementing what field to serialize and how.

Every time you update your code you will have the same issue with backward compatibility if you use the build in function.

matheszabi
  • 594
  • 5
  • 16
  • This'd work, but something important (I'll edit my question) I forgot: I cant change the original class source. – breakline Oct 25 '16 at 05:55
2

making it transient will exclude it from serialization

public transient SomeClass lastUpdatedAt;

according to jls-8.3.1.3

Variables may be marked transient to indicate that they are not part of the persistent state of an object.

ΦXocę 웃 Пepeúpa ツ
  • 47,427
  • 17
  • 69
  • 97
  • Same problem as above. I cant make any changes to the original source. Its a running service I need to update with a completely new one while also keeping legacy data serialized into files.... In short – breakline Oct 25 '16 at 05:57
0
ArrayList<MyClass> result = (ArrayList<MyClass>) is.readObject(); //fails

Actually this would fail, because the elements list signature doesn't match! Because MyClass has 1 or more field renamed, added, removed, type changed.

MyClass { int a; }

MyClass { String a; } 

will break the deserialization.

What you could try is to override the equals() and the hashCode() methods in order to make your MyClassNew to looks like MyClass.

Here you can see more how to override now the desired method. That should give you a solution.

   private void readObject(java.io.ObjectInputStream stream)
            throws IOException, ClassNotFoundException {
        location = (String) stream.readObject();
    }
Community
  • 1
  • 1
matheszabi
  • 594
  • 5
  • 16