Search code examples
javaserializationdeserializationexternalizable

Handle deserialization when datatype of class field changed


I have a serializable class.

public class Customer  implements Externalizable {

private static final long serialVersionUID = 1L;

    private String id;
    private String name;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public  String getName() {
        return name;
    }


    public void setName( String name) {
        this.name = name;
    }


    @Override
    public String toString() {
        return "id : "+id+" name : "+name ;
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException,
            ClassNotFoundException {
            this.setId((String) in.readObject());
            this.setName((String) in.readObject());     
    }

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        System.out.println("Reached here");
        out.writeObject(id);
        out.writeObject(name);
    }


}

I have serialized the object of the class into a file. Now I have changed the datatype of name from String to List. So while deserializing, I am getting a class cast exception because it is not able to convert from String to List. I was thinking of changing the version of the class every time some change is made to the class so that in the readExternal I can handle it explicitly. However while this idea might be able to work for simple classes it would fail in case of larger complicated classes. Can anyone please provide a simpler solution to this.

Thanks


Solution

  • You just have to manage the different possibilities (and perform the appropiate conversion) yourself.

    @Override
    public void readExternal(ObjectInput in) throws IOException,
      ClassNotFoundException {
      this.setId((String) in.readObject());
      Object nameField = in.readObject();
      if (nameField != null) {
        boolean resolved = false;
        if (nameField instanceof String) {
          ArrayList<String> list = new ArrayList<String>(); // Or whatever you want to for converting the String to list.
          list.add((String)nameField);
          this.setName(list);
          resolved = true;
        }
        if (nameField instanceof List) {
          this.setName((List<String>) nameField);
          resolved = true;
        }
        if (!resolved) {
          throw new Exception("Could not deserialize " + nameField + " into name attribute");
        }
      }
    }