web-dev-qa-db-fra.com

Conversion de LinkedHashMap en objet complexe

J'ai une application qui stocke des données dans DynamoDB en utilisant Jackson pour transformer mon objet complexe en JSON.

Par exemple, l'objet que je rassemble pourrait ressembler à ceci:

private String aString;
private List<SomeObject> someObjectList;

Où SomeObject pourrait ressembler à ceci:

private int anInteger;
private SomeOtherObject;

et SomeOtherObject pourrait ressembler à ceci:

private long aLong;
private float aFloat; 

Ceci est correct et l'objet est organisé sans problème et stocké dans la base de données sous forme de chaîne JSON.

Lorsque vient le temps de récupérer les données de DynamoDB, Jackson récupère automatiquement le JSON et le reconvertit ... SAUF que 'someObjectList' est renvoyé sous la forme d'un fichier List<LinkedHashMap> pas comme un List<SomeObject>! C'est un comportement standard pour Jackson, ce n'est pas une erreur que cela se produise.

Alors maintenant, cela pose un problème. Ma base de code pense qu'il s'agit d'un List<SomeObject> mais la réalité est que sa manipulation est un List<LinkedHashMap>! Ma question est de savoir comment puis-je obtenir mon LinkedHashMap dans un "SomeObject". Évidemment, il s'agit d'un processus manuel, mais ce que je veux dire, c'est que je ne peux même pas extraire les valeurs.

Si je fais ça:

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

Une erreur de compilation me dit que someObjectList est de type 'SomeObject' et non pas LinkedHashMap.

Si je fais ça:

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

Une erreur d'exécution me dit que LinkedHashMap ne peut pas être converti en 'SomeObject'.

49
tarka

Vous pouvez utiliser ObjectMapper.convertValue(), valeur par valeur ou même pour toute la liste. Mais vous devez connaître le type de conversion:

POJO pojo = mapper.convertValue(singleObject, POJO.class);
// or:
List<POJO> pojos = mapper.convertValue(listOfObjects, new TypeReference<List<POJO>>() { });

c'est fonctionnellement pareil que si vous l'aviez fait:

byte[] json = mapper.writeValueAsBytes(singleObject);
POJO pojo = mapper.readValue(json, POJO.class);

mais évite la sérialisation réelle des données en tant que JSON, utilisant plutôt une séquence d'événements en mémoire comme étape intermédiaire.

120
StaxMan

Il existe une bonne solution à ce problème:

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

Pourquoi ce problème est-il survenu? J'imagine que vous n'avez pas spécifié le type spécifique lors de la conversion d'une chaîne en objet, qui est une classe avec un type générique, tel que User <T>.

Peut-être existe-t-il un autre moyen de le résoudre, en utilisant Gson au lieu de ObjectMapper. (ou voir ici désériorisation des types génériques avec 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();
0
Donald Choi

J'avais un problème similaire où nous avons un objet GenericResponse contenant une liste de valeurs

 ResponseEntity<ResponseDTO> responseEntity = restTemplate.exchange(
                redisMatchedDriverUrl,
                HttpMethod.POST,
                requestEntity,
                ResponseDTO.class
        );

L'utilisation d'ObjectMapper a aidé à convertir LinkedHashMap en objets DTO respectifs

 ObjectMapper mapper = new ObjectMapper();

 List<DriverLocationDTO> driverlocationsList = mapper.convertValue(responseDTO.getData(), new TypeReference<List<DriverLocationDTO>>() { });
0
Aravind Rapuru