I have two class for external API response:
ClassA:
@JsonIgnoreProperties(ignoreUnknown = true)
@Getter
@Setter
public class ClassA {
private SubClass subClass;
@Getter
@Setter
public static class SubClass {
Integer total;
Integer perPage;
List<Data> dataList;
@Getter
@Setter
public static class Data {
private String field1;
private String field2;
private int field3;
}
}
}
ClassB:
@JsonIgnoreProperties(ignoreUnknown = true)
@Getter
@Setter
public class ClassB {
private SubClass subClass;
@Getter
@Setter
public static class SubClass {
Integer total;
Integer perPage;
List<Data> dataList;
@Getter
@Setter
public static class Data {
private String field1;
private int field2;
private Date field3;
}
}
}
And deserialization with ObjectMapper:
ClassA classA =
mapper.readValue(bodyResponse, ClassA.class);
What is the best way to get rid of duplicate code in these classes when using inheritance and later using deserialization?
CodePudding user response:
You need to make root and sub classes generic. Use TypeReference
to provide which data class you expect. Take a look at below example:
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.json.JsonMapper;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.util.Date;
import java.util.List;
public class GenericDataApp {
public static void main(String[] args) throws JsonProcessingException {
JsonMapper mapper = JsonMapper.builder().build();
String srcA = "{\"subClass\":{\"total\":1,\"dataList\":[{\"field2\":\"String value\"}]}}";
RootClass<DataA> dataA = mapper.readValue(srcA, new TypeReference<RootClass<DataA>>() {
});
System.out.println(dataA.getSubClass());
String srcB = "{\"subClass\":{\"total\":1,\"dataList\":[{\"field2\":12}]}}";
RootClass<DataB> dataB = mapper.readValue(srcB, new TypeReference<RootClass<DataB>>() {
});
System.out.println(dataB.getSubClass());
}
}
@JsonIgnoreProperties(ignoreUnknown = true)
@Getter
@Setter
class RootClass<T> {
private SubClass<T> subClass;
@Getter
@Setter
@ToString
public static class SubClass<T> {
Integer total;
Integer perPage;
List<T> dataList;
}
}
@Getter
@Setter
@ToString
class DataA {
private String field1;
private String field2;
private int field3;
}
@Getter
@Setter
@ToString
class DataB {
private String field1;
private int field2;
private Date field3;
}
Above code prints:
RootClass.SubClass(total=1, perPage=null, dataList=[DataA(field1=null, field2=String value, field3=0)])
RootClass.SubClass(total=1, perPage=null, dataList=[DataB(field1=null, field2=12, field3=null)])