Umwandeln von LinkedHashMap in ein komplexes Objekt

Lesezeit: 4 Minuten

Benutzer-Avatar
Tarka

Ich habe eine Anwendung, die einige Daten in DynamoDB speichert und Jackson verwendet, um mein komplexes Objekt in ein JSON zu marshallieren.

Zum Beispiel könnte das Objekt, das ich marshalle, so aussehen:

private String aString;
private List<SomeObject> someObjectList;

Wobei SomeObject so aussehen könnte:

private int anInteger;
private SomeOtherObject;

und SomeOtherObject könnte so aussehen:

private long aLong;
private float aFloat; 

Das ist in Ordnung und das Objekt wird problemlos gemarshallt und in der DB als JSON-String gespeichert.

Wenn es an der Zeit ist, die Daten von DynamoDB abzurufen, ruft Jackson automatisch den JSON ab und konvertiert ihn zurück … AUSSER dass „someObjectList“ als zurückgegeben wird List<LinkedHashMap> nicht als List<SomeObject>! Das ist Standardverhalten für Jackson, es ist kein Fehler, dass das passiert.

Das führt jetzt also zu einem Problem. Meine Codebasis denkt, dass es sich um a handelt List<SomeObject> aber die Realität ist, dass seine Handhabung a List<LinkedHashMap>! Meine Frage ist, wie ich meine LinkedHashMap wieder in ein ‘SomeObject’ bekomme. Offensichtlich ist dies ein manueller Prozess, aber ich meine, ich kann nicht einmal die Werte extrahieren.

Wenn ich das mache:

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

Ich erhalte einen Kompilierungsfehler, der mir mitteilt, dass someObjectList vom Typ „SomeObject“ und nicht LinkedHashMap ist.

Wenn ich das mache:

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

Ich erhalte einen Laufzeitfehler, der mir mitteilt, dass LinkedHashMap nicht in „SomeObject“ umgewandelt werden kann.

  • convertValue hat bei mir funktioniert

    – Gaurav

    23. März um 21:15 Uhr

Sie können verwenden ObjectMapper.convertValue(), entweder Wert für Wert oder sogar für die gesamte Liste. Aber Sie müssen den Typ kennen, in den konvertiert werden soll:

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

Dies ist funktional dasselbe, als ob Sie Folgendes getan hätten:

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

vermeidet jedoch die eigentliche Serialisierung von Daten als JSON und verwendet stattdessen eine In-Memory-Ereignissequenz als Zwischenschritt.

  • Das zweite Beispiel erfordert jedoch keinen statischen Verweis auf den POJO-Typ.

    – Bo Søborg Petersen

    26. Februar 2016 um 13:42 Uhr

  • Genial. Das einzige, was ich tun musste, war sicherzustellen, dass die POJO-Klasse einen Standardkonstruktor enthält (falls andere parametrisierte Konstruktoren vorhanden sind).

    – Gnana

    3. März 2016 um 22:33 Uhr

  • Ich meine, dass beim ersten Beispiel der Typ zur Entwurfszeit bekannt sein muss. Sie können den Typ des Objekts nicht einfach an die (De-) Serialisierungsmethode übergeben, was ein Problem darstellt, wenn Sie eine Methode zum (De-) Serialisieren einer beliebigen Klasse erstellen. Beim zweiten Beispiel können Sie einfach .getClass() für die Serialisierung verwenden und den Typ für die Deserialisierung übergeben.

    – Bo Søborg Petersen

    12. April 2016 um 15:23 Uhr

  • @BoSøborgPetersen Ok, das stimmt mit TypeReferenceaber man kann konstruieren List tippe mit TypeFactory (constructCollectionType(elementType) oder dergleichen), keine allgemeine Einschränkung.

    – StaxMan

    14. April 2016 um 4:08 Uhr

  • Nur eine kurze Anmerkung für neue Leser: Die TypeReference-Klasse im Code-Snippet stammt von „com.fasterxml.jackson.core.type.TypeReference“.

    – AliReza

    17. Januar 2020 um 19:59 Uhr

Benutzer-Avatar
Aravind Rapuru

Ich hatte ein ähnliches Problem, bei dem wir ein GenericResponse-Objekt haben, das eine Werteliste enthält

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

Die Verwendung von objectMapper half bei der Konvertierung von LinkedHashMap in entsprechende DTO-Objekte

 ObjectMapper mapper = new ObjectMapper();

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

Benutzer-Avatar
Donald Choi

Für dieses Problem gibt es eine gute Lösung:

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

Warum ist dieses Problem aufgetreten? Ich vermute, Sie haben beim Konvertieren einer Zeichenfolge in das Objekt, bei dem es sich um eine Klasse mit einem generischen Typ handelt, wie z. B. Benutzer , keinen bestimmten Typ angegeben.

Vielleicht gibt es eine andere Möglichkeit, das Problem zu lösen, indem Sie Gson anstelle von ObjectMapper verwenden. (oder siehe hier Generische Typen mit GSON deserialisieren)

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

  • Bitte auch um Erklärung 🙂

    – Mohit Motwani

    20. März 2019 um 9:36 Uhr

  • Dieses Code-Snippet könnte zwar die Lösung sein, inklusive Erklärung hilft wirklich, die Qualität Ihres Beitrags zu verbessern. Denken Sie daran, dass Sie die Frage für zukünftige Leser beantworten und diese Personen die Gründe für Ihren Codevorschlag möglicherweise nicht kennen.

    – Johann

    20. März 2019 um 9:37 Uhr

  • @Johan OK, danke für die Warnung. Ich bin ein Neuling für die Beantwortung einiger Fragen zu Stack Overflow, also werde ich es in Zukunft besser machen.

    – Donald Choi

    19. April 2019 um 7:12 Uhr


Benutzer-Avatar
vuhoanghiep1993

Ich verwende com.fasterxml.jackson.databind.ObjectMapper zum Zuordnen von LinkedHashMap zu Json-String zuerst und konvertiere von Json-String zu 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;
}

1257570cookie-checkUmwandeln von LinkedHashMap in ein komplexes Objekt

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy