0
votes

I have a requirement to change properties of a class which is being serialized/deserialized by ObjectMapper.

This is my class.

// Old version
Class A {
    String id;
    String name;
}

// New version
Class A {
    String id;
    String firstName;
    String secondName;
}

I serialize the object ObjectMapper.writeValueAsString(), send it to a queue to process it later, and when received, deserialize it via ObjectMapper.readValue(). What is the expected behavior of readValue() if the old version of Class A is serialized, but when deserializing - Class A has been updated to the new version.

Will firstName and secondName be null? Or readValue() throw an exception?

And what is the solution here to make the changes smoothly.

1
So what you want to do is migrating your data from an old version of A to a new version of A? So you dump your data using the old A and then read it again after you changed your class A to the new version? Do I understand correctly? - gilgwath
@paradoxon I want to essentially update Class A without any side effects to the application. Before deploying the change I will have multiple serialized objects in my Queue, after deployment when these messages are read and objects deserialized, how do I make sure they work as expected - Dhiresh Jain
When deserializing does the json string include firstName and secondName or you are expecting objectmapper to spring name into firstName and secondName? - Coder
No it will post null values for firstName and secondName. I want to design a solution were I can make the transition without affecting my application negatively - Dhiresh Jain

1 Answers

0
votes

To answer the first part as to what is the expected behavior if older object is deserialized, objectMapper.readValue() will deserialize with firstName and secondName being null while name being whatever was set. (I was expecting an exception which is not the case).

On how to make the transition:

I will not delete name. I will keep it along with firstName and secondName.

// Intermediate version
Class A {
    String id;
    String name;
    String firstName;
    String secondName;
}

name will be a dummy holder, and not used when serializing.

public void write(int id, String firstName, String secondName) {
    A a = new A();
    a.setId(id);
    a.setFirstName(firstName);
    a.setSecondName(secondName);
    bufferedWriter.write(objectMapper.writeValueAsString(a));
}

Based on null check I will know whether the object belongs to older version or newer version.

public void read(String message) {
    A a = objectMapper.readValue(message);

    if(a.getName() != null) {
        // This object is older version of class A
        System.out.println("Name: " + a.getName());
        metric.emit("OldObjectA", 1);
    } else {
        // This object is newer version of class A
        System.out.println("Name: " + a.getFirstName() + " " + a.getSecondName())
    }
}

Once I'm sure I am not reading objects of older version, I will make the complete transition by removing name.

// Newer version
Class A {
    String id;
    String firstName;
    String secondName;
}