将 LinkedHashMap 转换为复杂对象

我有一个应用程序,它在 DynamoDB 中存储一些数据,使用 Jackson 将我的复杂对象封装成一个 JSON。

例如,我正在编组的对象可能如下所示:

private String aString;
private List<SomeObject> someObjectList;

有些对象可能看起来像这样:

private int anInteger;
private SomeOtherObject;

另一个对象可能是这样的:

private long aLong;
private float aFloat;

如果对象没有问题地进行编组,并以 JSON 字符串的形式存储在 DB 中,那么这样做很好。

当需要从 DynamoDB Jackson 检索数据时,Jackson 会自动检索 JSON 并将其转换回来... ... 除了‘ some ObjectList’作为 List<LinkedHashMap>而不是 List<SomeObject>返回!这是杰克逊的标准行为,这不是一个错误。

所以这就引出了一个问题。我的代码库认为它处理的是 List<SomeObject>,但实际上它处理的是 List<LinkedHashMap>!我的问题是如何让我的 LinkedHashMap 重新变成一个‘ Some Object’。显然,这是一个手工过程,但我的意思是,我甚至不能提取值。

如果我这样做:

for (LinkedHashMap lhm : someObjectList) {
// Convert the values back
}

我得到一个编译错误,它告诉我 some ObjectList 的类型是‘ Some Object’而不是 LinkedHashMap。

如果我这样做:

for (SomeObject lhm : someObjectList) {
// Convert the values back
}

我得到一个运行时错误,告诉我 LinkedHashMap 不能被强制转换为‘ Some Object’。

158841 次浏览

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.

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

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

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;
}

public static <T> List<T> getObjectList(final String json, final Class<T> cls) {

return objectMapper.readValue(json, objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, cls));

}

First you have to convert linkedhashmap to JsonString and then it can be converted into complex object.