mzlo
mzlo

Reputation: 353

How to handle backward compatibility (field name change) in Jackson?

Suppose I use schema from library (not owned by me)

class OldClass {
   int id;
   string name;
}

Serialised JSON "SerJsonStr" would like

{"id": 12, "name": "Bob"}

Now I can use "OldClass" schema and above example json to deserialise json into scala Object

OldClass obj = new ObjectMapper().readValue[OldClass](SerJsonStr)

But, suppose library updates schema (by changing field name) to

class OldClass {
   int id;
   string **fullName**;
}

Now, deserialisation will set fullName to null for backward compatibility. Note that "OldClass" is part of third-party library not owned by me

Is there any way to explicitly specify Map["name" -> "full name"] and then

  customizedFieldNameChange["name"] = "fullName"
  OldClass obj = new ObjectMapper().readValue[OldClass]({"id": 12, "name": "Bob"}, customizedFieldNameChange)

will set fullName to "Bob" (i.e. it will invoke setFullName() on "obj" for "name" field in json string) ?

Upvotes: 1

Views: 1285

Answers (1)

Anand
Anand

Reputation: 927

You have to use JsonDeserializer to dynamically read values from the json.

Below is a Java example,

public class CustomDeserializer extends JsonDeserializer<OldClass> {
    @Override
    public OldClass deserialize(JsonParser jsonParser, DeserializationContext context)
            throws IOException, JsonProcessingException {
        JsonNode node = jsonParser.getCodec().readTree(jsonParser);
        int id = (Integer) ((IntNode) node.get("id")).numberValue();
        String fullName = node.get("name").asText();
        return new OldClass(id, fullName);
    }
}

Finally, to deserialize

ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(OldClass.class, new CustomDeserializer());
mapper.registerModule(module);
OldClass values = mapper.readValue(json, OldClass.class);

For detailed explanation check this tutorial

Upvotes: 1

Related Questions