java.lang.ClassCastException: java.util.LinkedHashMap kann nicht in com.testing.models.Account umgewandelt werden
Lesezeit: 6 Minuten
Leidenschaftlicher Ingenieur
Ich bekomme folgenden Fehler:
java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.testing.models.Account
mit untenstehendem Code
final int expectedId = 1;
Test newTest = create();
int expectedResponseCode = Response.SC_OK;
ArrayList<Account> account = given().when().expect().statusCode(expectedResponseCode)
.get("accounts/" + newTest.id() + "https://stackoverflow.com/users")
.as(ArrayList.class);
assertThat(account.get(0).getId()).isEqualTo(expectedId);
Gibt es einen Grund, warum ich das nicht kann get(0)?
Kann nicht gecastet werden was? Wie lautet der Rest der Fehlermeldung?
– Oliver Charlesworth
3. März 2015 um 0:02 Uhr
@OliverCharlesworth hat auch den gesamten Stacktrace hinzugefügt
– Leidenschaftlicher Ingenieur
3. März 2015 um 0:05 Uhr
Was ist ein Account? Warum versuchst du, von einer Karte darauf zu werfen?
– David Newton
3. März 2015 um 0:06 Uhr
Können Sie für diejenigen von uns, die mit der Bibliothek nicht vertraut sind, sagen, welche Klasse das ist? given() Methode wird statisch importiert?
– Markus Peters
3. März 2015 um 0:07 Uhr
@DaveNewton Account ist ein Modell von Dropwizard, das verwendet com.fasterxml.jackson.databind.annotations
– Leidenschaftlicher Ingenieur
3. März 2015 um 0:08 Uhr
Markus Peters
Das Problem kommt von Jackson. Wenn es nicht genügend Informationen darüber hat, in welche Klasse es deserialisiert werden soll, verwendet es LinkedHashMap.
Da Sie Jackson nicht über den Elementtyp Ihrer informieren ArrayListweiß es nicht, dass Sie in ein deserialisieren möchten ArrayList von Accounts. Es fällt also auf die Voreinstellung zurück.
Stattdessen könnten Sie wahrscheinlich verwenden as(JsonNode.class)und beschäftigen Sie sich dann mit der ObjectMapper auf reichere Art und Weise, als es die Zuversicht zulässt. Etwas wie das:
ObjectMapper mapper = new ObjectMapper();
JsonNode accounts = given().when().expect().statusCode(expectedResponseCode)
.get("accounts/" + newClub.getOwner().getCustId() + "/clubs")
.as(JsonNode.class);
//Jackson's use of generics here are completely unsafe, but that's another issue
List<Account> accountList = mapper.convertValue(
accounts,
new TypeReference<List<Account>>(){}
);
assertThat(accountList.get(0).getId()).isEqualTo(expectedId);
Sie können die Antwort auch als String () festlegen, was zusätzliche Konvertierungen erspart – readValue akzeptiert einen String als erstes Argument.
– BIGDeutsch
9. Juni 2016 um 9:25 Uhr
@BIGDeutsch: Wenn ich das nur noch einmal durchgehe, war es nicht nötig, dass ich dort wieder in Token umwandelte convertValue könnte es in einem Schritt tun. Zu einer Zeichenfolge zu gehen funktioniert auch.
– Markus Peters
6. März 2019 um 17:07 Uhr
was zu tun ist, wenn ein Objekt eine Variable enthält, die list ist. Wie deserialisiert man das Objekt mit Jackson?
List<POJO> pojos = mapper.convertValue(
listOfObjects,
new TypeReference<List<POJO>>() { });
Weitere Informationen finden Sie unter Konvertierung von LinkedHashMap.
+1 für das Anzeigen von “convertValue”. Ich hatte einen Fall, in dem ich eine bestimmte Eigenschaft aus json als Liste auslesen musste, und das ist genau das, was ich brauchte.
– GameSalutes
20. Juni 2017 um 21:02 Uhr
So konnte ich das abmildern JSON-Array zur Sammlung von LinkedHashMap-Objekten Problem war durch die Verwendung CollectionType eher als ein TypeReference . Das habe ich getan und hat funktioniert:
Verwendung der TypeReferenceich bekam immer noch eine ArrayList von LinkedHashMaps, dh funktioniert nicht:
public <T> List<T> jsonArrayToObjectList(String json, Class<T> tClass) throws IOException {
ObjectMapper mapper = new ObjectMapper();
List<T> ts = mapper.readValue(json, new TypeReference<List<T>>(){});
LOGGER.debug("class name: {}", ts.get(0).getClass().getName());
return ts;
}
Hat mein Problem auch gespeichert. Vielen Dank!
– Wladimir Gilewitsch
5. Oktober 2017 um 14:53 Uhr
+1, der Unterschied in Ihrem Fall war, dass die Methode selbst so generisch war T konnte nicht über das TypeToken verifiziert werden, was normalerweise einfacher ist. Persönlich bevorzuge ich den Helfer von Guava, weil er immer noch typsicher und nicht spezifisch für einen Containertyp ist: return new TypeToken<List<T>>(){}.where(new TypeParameter<T>(){}, tClass). Aber Jackson nimmt nicht TypeTokens so brauchen Sie dann .getType().
– Markus Peters
24. November 2017 um 15:22 Uhr
Hat mein Problem auch gespeichert. Vielen Dank!
– Schaschenk
17. Juli 2020 um 3:32 Uhr
Vielen Dank! Ich habe viel Zeit damit verbracht, diesen Fehler zu beheben, bis ich diese Antwort gefunden habe !!
– glco
8. Dezember 2020 um 18:33 Uhr
Schön!!. Das hat mir auch den Tag gerettet 🙂 .. Ich habe stundenlang gekämpft, bevor ich diese Lösung gefunden habe. Ich habe versucht, einen generischen JSONB-Array-Konverter für JOOQ in Kotlin zu schreiben.
– sumanr
23. Februar 2021 um 12:45 Uhr
nurb
Ich hatte eine ähnliche Ausnahme (aber ein anderes Problem) – java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to org.bson.Document und zum Glück ist es einfacher zu lösen:
was einen Fehler in der zweiten Zeile gibt, kann man verwenden
List<Document> docs = obj.get("documents");
Document doc = new Document(docs.get(0));
Lösen Sie das Problem mit zwei Methoden parse common
Der Typ ist ein Objekt
public <T> T jsonToObject(String json, Class<T> type) {
T target = null;
try {
target = objectMapper.readValue(json, type);
} catch (Jsenter code hereonProcessingException e) {
e.printStackTrace();
}
return target;
}
With type ist ein Collection-Wrap-Objekt
public <T> T jsonToObject(String json, TypeReference<T> type) {
T target = null;
try {
target = objectMapper.readValue(json, type);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return target;
}
siddharth jain
Dies ist etwas, das ich in meinem Projekt verwendet habe, Json-Objekt wurde zurückgegeben, ich habe es in eine Liste von POJO, List konvertiert und dann auf das Element zugegriffen. Ich habe die Eingabe des Json-Objekts von einem anderen Microservice übernommen.
Hauptsache: – JsonNode stocks = restTemplate.getForObject(“http://localhost:2000/stocks/qty”, JsonNode.class); List stockList = mapper.convertValue(stocks, new TypeReference>() {});
@GetMapping("/")
public List<Stock_id_qty> checkQty() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
JsonNode stocks = restTemplate.getForObject("http://localhost:2000/stocks/qty", JsonNode.class);
List<Stock_id_qty> stockList = mapper.convertValue(stocks, new TypeReference<List<Stock_id_qty>>() {});
List<Stock_id_qty> result = new ArrayList<>();
for(Stock_id_qty s : stockList){
if(s.getStockQty() < 10)
{
result.add(s);
}
}
return result;
}
Ishaan Javali
Ich habe diese Methode zum Deserialisieren eines XML und Konvertieren des Typs:
public <T> Object deserialize(String xml, Class objClass ,TypeReference<T> typeReference ) throws IOException {
XmlMapper xmlMapper = new XmlMapper();
Object obj = xmlMapper.readValue(xml,objClass);
return xmlMapper.convertValue(obj,typeReference );
}
Kann nicht gecastet werden was? Wie lautet der Rest der Fehlermeldung?
– Oliver Charlesworth
3. März 2015 um 0:02 Uhr
@OliverCharlesworth hat auch den gesamten Stacktrace hinzugefügt
– Leidenschaftlicher Ingenieur
3. März 2015 um 0:05 Uhr
Was ist ein
Account
? Warum versuchst du, von einer Karte darauf zu werfen?– David Newton
3. März 2015 um 0:06 Uhr
Können Sie für diejenigen von uns, die mit der Bibliothek nicht vertraut sind, sagen, welche Klasse das ist?
given()
Methode wird statisch importiert?– Markus Peters
3. März 2015 um 0:07 Uhr
@DaveNewton
Account
ist ein Modell von Dropwizard, das verwendetcom.fasterxml.jackson.databind.annotations
– Leidenschaftlicher Ingenieur
3. März 2015 um 0:08 Uhr