Casting LinkedHashMap to Complex Object
JavaCastingJacksonLinkedhashmapJava Problem Overview
I've got an application that stores some data in DynamoDB using Jackson to marshall my complex object into a JSON.
For example the object I'm marshalling might look like this:
private String aString;
private List<SomeObject> someObjectList;
Where SomeObject might look like this:
private int anInteger;
private SomeOtherObject;
and SomeOtherObject might look like this:
private long aLong;
private float aFloat;
This is fine an the object gets marshalled no problem and stored in the DB as a JSON string.
When it comes time to retrieve the data from DynamoDB Jackson automatically retrieves the JSON and converts it back... EXCEPT that 'someObjectList' is returned as a List<LinkedHashMap>
not as a List<SomeObject>
! This is standard behaviour for Jackson, its not a mistake that this is happening.
So now this leads to a problem. My code base thinks its dealing with a List<SomeObject>
but the reality is that its handling a List<LinkedHashMap>
! My question is how do I get my LinkedHashMap back into a 'SomeObject'. Obviously this is a manual process but what I mean is I can't even extract the values.
If I do this:
for (LinkedHashMap lhm : someObjectList) {
// Convert the values back
}
I get a compile error telling me that someObjectList is of type 'SomeObject' not LinkedHashMap.
If I do this:
for (SomeObject lhm : someObjectList) {
// Convert the values back
}
I get a runtime error telling me that LinkedHashMap cannot be cast to 'SomeObject'.
Java Solutions
Solution 1 - Java
You can use ObjectMapper.convertValue()
, either value by value or even for the whole list. But you need to know the type to convert to:
POJO pojo = mapper.convertValue(singleObject, POJO.class);
// or:
List<POJO> pojos = mapper.convertValue(listOfObjects, new TypeReference<List<POJO>>() { });
this is functionally same as if you did:
byte[] json = mapper.writeValueAsBytes(singleObject);
POJO pojo = mapper.readValue(json, POJO.class);
but avoids actual serialization of data as JSON, instead using an in-memory event sequence as the intermediate step.
Solution 2 - Java
I had similar Issue where we have GenericResponse object containing list of values
ResponseEntity<ResponseDTO> responseEntity = restTemplate.exchange(
redisMatchedDriverUrl,
HttpMethod.POST,
requestEntity,
ResponseDTO.class
);
Usage of objectMapper helped in converting LinkedHashMap into respective DTO objects
ObjectMapper mapper = new ObjectMapper();
List<DriverLocationDTO> driverlocationsList = mapper.convertValue(responseDTO.getData(), new TypeReference<List<DriverLocationDTO>>() { });
Solution 3 - Java
There is a good solution to this issue:
import com.fasterxml.jackson.databind.ObjectMapper;
ObjectMapper objectMapper = new ObjectMapper();
***DTO premierDriverInfoDTO = objectMapper.convertValue(jsonString, ***DTO.class);
Map<String, String> map = objectMapper.convertValue(jsonString, Map.class);
Why did this issue occur? I guess you didn't specify the specific type when converting a string to the object, which is a class with a generic type, such as, User <T>.
Maybe there is another way to solve it, using Gson instead of ObjectMapper. (or see here Deserializing Generic Types with GSON)
Gson gson = new GsonBuilder().create();
Type type = new TypeToken<BaseResponseDTO<List<PaymentSummaryDTO>>>(){}.getType();
BaseResponseDTO<List<PaymentSummaryDTO>> results = gson.fromJson(jsonString, type);
BigDecimal revenue = results.getResult().get(0).getRevenue();
Solution 4 - Java
I use com.fasterxml.jackson.databind.ObjectMapper to mapping from LinkedHashMap to Json string first and convert from json string to Object
Map<String, String> mappingValue
OBJECTA a = objectMapper.readValue(toJson(mappingValue), OBJECTA.class);
public static String toJson(Object object) {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
String jsonString = "";
try {
jsonString = mapper.writeValueAsString(object);
} catch (JsonProcessingException var4) {
var4.printStackTrace();
jsonString = "Can't build json from object";
}
return jsonString;
}