Reputation: 139
I have the following Json
{
"coreId" : "1",
"name" : "name",
"additionalValueList" : [
{
"columnName" : "allow_duplicate",
"rowId" : "10",
"value" : "1"
},
{
"columnName" : "include_in_display",
"rowId" : "11",
"value" : "0"
},
...e.t.c
]
},
...e.t.c
and Java class
class DTO {
@JsonProperty("coreId")
private Integer id;
private String name;
private Boolean allowDuplicate;
private Boolean includeInDisplay;
}
How I can easily map values from 'additionalValueList' to corresponding java fields.For example Json value from field 'columnName' - 'allow_duplicate' = DTO.allowDuplicate. Actually I know how to do it with custom deserializers with @JsonDeserialize annotation and smth like this.Bu I have 40+ DTO and it is not a good idea to create own deserializer for each filed. I am looking for solution to have for example 1 deserializer(since values structure in 'additionalValueList' are the same for all entities) and to pass parameter(field name that I want to map to that field) to custom deserializer that will find in 'additionalValueList' entity with 'column Name' = parameter(that I passed from annotation) and return 'value'. Example
class DTO {
@JsonProperty("coreId")
private Integer id;
private String name;
@JsonDeserialize(using = MyCustDeser.class,param = allow_duplicate)
private Boolean allowDuplicate;
@JsonDeserialize(using = MyCustDeser.class,param = include_in_display)
private Boolean includeInDisplay;
}
It will be a good solution but maybe not easy to achieve.However I will be very grateful for all your advices.Thank you.
Upvotes: 1
Views: 705
Reputation: 159135
Create a Converter
class, then specify it on the DTO class.
The following code uses public
fields for the simplicity of the example.
/**
* Intermediate object used for deserializing FooDto from JSON.
*/
public final class FooJson {
/**
* Converter used when deserializing FooDto from JSON.
*/
public static final class ToDtoConverter extends StdConverter<FooJson, FooDto> {
@Override
public FooDto convert(FooJson json) {
FooDto dto = new FooDto();
dto.name = json.name;
dto.id = json.coreId;
dto.allowDuplicate = lookupBoolean(json, "allow_duplicate");
dto.includeInDisplay = lookupBoolean(json, "include_in_display");
return dto;
}
private static Boolean lookupBoolean(FooJson json, String columnName) {
String value = lookup(json, columnName);
return (value == null ? null : (Boolean) ! value.equals("0"));
}
private static String lookup(FooJson json, String columnName) {
if (json.additionalValueList != null)
for (FooJson.Additional additional : json.additionalValueList)
if (columnName.equals(additional.columnName))
return additional.value;
return null;
}
}
public static final class Additional {
public String columnName;
public String rowId;
public String value;
}
public Integer coreId;
public String name;
public List<Additional> additionalValueList;
}
You now simply annotate the DTO to use it:
@JsonDeserialize(converter = FooJson.ToDtoConverter.class)
public final class FooDto {
public Integer id;
public String name;
public Boolean allowDuplicate;
public Boolean includeInDisplay;
@Override
public String toString() {
return "FooDto[id=" + this.id +
", name=" + this.name +
", allowDuplicate=" + this.allowDuplicate +
", includeInDisplay=" + this.includeInDisplay + "]";
}
}
Test
ObjectMapper mapper = new ObjectMapper();
FooDto foo = mapper.readValue(new File("test.json"), FooDto.class);
System.out.println(foo);
Output
FooDto[id=1, name=name, allowDuplicate=true, includeInDisplay=false]
Upvotes: 1