web-dev-qa-db-fra.com

java.lang.ClassCastException: Java.util.LinkedHashMap ne peut pas être converti en com.testing.models.Account

Je reçois une erreur en dessous:

Java.lang.ClassCastException: Java.util.LinkedHashMap cannot be cast to com.testing.models.Account

avec le code ci-dessous

final int expectedId = 1;

Test newTest = create();

int expectedResponseCode = Response.SC_OK;

ArrayList<Account> account = given().when().expect().statusCode(expectedResponseCode)
    .get("accounts/" + newTest.id() + "/users")
    .as(ArrayList.class);
assertThat(account.get(0).getId()).isEqualTo(expectedId);

Y a-t-il une raison pour laquelle je ne peux pas faire get(0)?

43

Le problème vient de Jackson. Lorsqu'il ne dispose pas de suffisamment d'informations sur la classe dans laquelle désérialiser, il utilise LinkedHashMap

Puisque vous n'informez pas Jackson du type d'élément de votre ArrayList, il ne sait pas que vous souhaitez effectuer une désérialisation dans une ArrayList de Accounts. Donc, il revient à la valeur par défaut.

Au lieu de cela, vous pourriez probablement utiliser as(JsonNode.class), puis traiter le ObjectMapper de manière plus riche que ce que permet le repos assuré. Quelque chose comme ça:

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.readValue(
    mapper.treeAsTokens(accounts), 
    new TypeReference<List<Account>>(){}
);

assertThat(accountList.get(0).getId()).isEqualTo(expectedId);
52
Mark Peters

Essayez ce qui suit:

POJO pojo = mapper.convertValue(singleObject, POJO.class);

ou:

List<POJO> pojos = mapper.convertValue(
    listOfObjects,
    new TypeReference<List<POJO>>() { });

Voir conversion de LinkedHashMap pour plus d'informations.

18
user2578871

La façon dont j'ai pu atténuer le tableau JSON à la collection d'objets LinkedHashMap problème a été d'utiliser CollectionType plutôt qu'un TypeReference . C'est ce que j'ai fait et travaillé :

public <T> List<T> jsonArrayToObjectList(String json, Class<T> tClass) throws IOException {
    ObjectMapper mapper = new ObjectMapper();
    CollectionType listType = mapper.getTypeFactory().constructCollectionType(ArrayList.class, tClass);
    List<T> ts = mapper.readValue(json, listType);
    LOGGER.debug("class name: {}", ts.get(0).getClass().getName());
    return ts;
}

En utilisant TypeReference, je continuais à obtenir une liste de tableaux de LinkedHashMaps, c.-à-d. ne fonctionne pas :

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;
}
15
Himadri Pant

J'ai eu une exception similaire (mais problème différent) - Java.lang.ClassCastException: Java.util.LinkedHashMap cannot be cast to org.bson.Document, et heureusement, cela a été résolu plus facilement:

Au lieu de 

List<Document> docs = obj.get("documents");
Document doc = docs.get(0)

qui donne une erreur en seconde ligne, on peut utiliser 

List<Document> docs = obj.get("documents");
Document doc = new Document(docs.get(0));
3
nurb

J'ai cette méthode pour désérialiser un fichier XML et convertir le type:

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

et c'est l'appel:

List<POJO> pojos = (List<POJO>) MyUtilClass.deserialize(xml, ArrayList.class,new TypeReference< List< POJO >>(){ });
0
Mohamed Farghaly