in Jackson, you have the mixin feature. This allows to add or override annotations at run time.
so we have one target POJO
public class Person { private String name; private int age; public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } }
and the mixin classes can be interfaces (they never get initialized) with matching setter method signatures and different annotations
public interface NameModel { @JsonProperty("name") void setName(String name); @JsonProperty("age") void setAge(int age); } public interface TitleModel { @JsonProperty("title") void setName(String name); @JsonProperty("years") void setAge(int age); }
at run-time you can associate one mixin to the target class. Jackson matches properties and methods by name and takes the annotations from the mixin. overriding any from the target:
public static void main(String[] args) { String nameModelJson = "{\"name\":\"title1\",\"age\":31}"; try (InputStream is = new ByteArrayInputStream(nameModelJson.getBytes())) { ObjectMapper mapper = new ObjectMapper(); mapper.addMixIn(Person.class, NameModel.class); Person p = mapper.readValue(is, Person.class); System.out.println(p.name + " " + p.age); } catch (Exception e) { e.printStackTrace(); } String titleModelJson = "{\"title\":\"title1\",\"years\":\"31\"}"; try (InputStream is = new ByteArrayInputStream(titleModelJson.getBytes())) { ObjectMapper mapper = new ObjectMapper(); mapper.addMixIn(Person.class, TitleModel.class); Person p = mapper.readValue(is, Person.class); System.out.println(p.name + " " + p.age); } catch (Exception e) { e.printStackTrace(); } }