Crazyk Crazyk - 4 months ago 16
JSON Question

How to deserialize JSON to complex POJO<> with List of Generic Objects

I use

jackson-databind 2.8.0

I have object with Generic Data

public class JsonItem<T> implements Serializable {

private static final long serialVersionUID = -8435937749132073097L;

@JsonProperty(required = true)
private boolean success;

@JsonProperty(required = false)
private T data;

@JsonProperty(required = false)
private Map<String, String> errors = new HashMap<>();

JsonItem() {
}

public boolean getSuccess() {
return success;
}

public void setSuccess(boolean success) {
this.success = success;
}

public T getData() {
return data;
}

public void setData(T data) {
this.data = data;
}

public Map<String, String> getErrors() {
return errors;
}

public void setErrors(Map<String, String> errors) {
this.errors = errors;
}
}


and have Object


@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class DepositInfoDto implements Serializable {

private static final long serialVersionUID = -4123441934244992311L;

@NotNull
@JsonProperty(required = true)
private String productName;

@NotNull
@JsonProperty(required = true)
private String contractName;

@NotNull
@JsonProperty(required = true)
private List<ContractDto> contracts;

@NotNull
@JsonProperty(required = true)
private StatusDto status;
//...getters and setters
}


I recevied object like
JsonItem<List<DepositInfoDto>>
.

I try to create universal method to deserealize


public <T> List<T> getObjects(){
ObjectMapper mapper = new ObjectMapper();
List<T> myObjects = mapper.readValue(jsonInput, new TypeReference<JsonItem<List<T>>(){});
return myObjects;
}


Not work because T cast to Object in runtime

public List<DepositInfoDto> getObjects(){
ObjectMapper mapper = new ObjectMapper();
List<DepositInfoDto> myObjects = mapper.readValue(jsonInput, new TypeReference<JsonItem<List<DepositInfoDto >>(){});
return myObjects;
}


work but i want universal method because i have
DepositInfoDto, CardinfoDto, ContractDto
etc.

I see method


public List<T> getObjects(Class<T> clazz){
ObjectMapper mapper = new ObjectMapper();
List<T> myObjects = mapper.readValue(jsonInput, mapper.getTypeFactory().constructCollectionType(List.class, clazz));
return myObjects;
}


but didn't work because i have
JsonItem
with data
List<T>


How can i resolve this problem? Maybe
mapper.getTypeFactory()
have complex method like
mapper.getTypeFactory().constructType(JsonItem.class, List.class,DepositInfoDto.class)


EDIT

In my case


ObjectMapper mapper = new ObjectMapper();
try {
JsonItem<T> item = mapper.readValue(objectWrapper.get(0), mapper.getTypeFactory().constructParametricType(
JsonItem.class, mapper.getTypeFactory().constructCollectionType(List.class, resourceClass)));
return item.getData();
} catch (IOException e) {
LOG.error("Can't deserialize JSON to class: "+ resourceClass +". Error: " + e);
Thread.currentThread().interrupt();
}

Answer

You can use TypeFactory#constructParametricType to create a JavaType for JsonItem<T> and then use TypeFactory#constructCollectionType to create CollectionType for List<JsonItem<T>>. Following is the example:

public <T> List<JsonItem<T>> getObjects(String jsonInput, Class<T> clazz) {

    ObjectMapper mapper = new ObjectMapper();
    return mapper.readValue(jsonInput, mapper.getTypeFactory().constructCollectionType(
           List.class, mapper.getTypeFactory().constructParametricType(JsonItem.class, clazz)));
}
Comments