Casting LinkedHashMap to Complex Object

淺唱寂寞╮ 提交于 2019-12-17 08:30:09

问题


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'.


回答1:


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.




回答2:


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>>() { });



回答3:


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();


来源:https://stackoverflow.com/questions/15430715/casting-linkedhashmap-to-complex-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!