java.lang.ClassCastException: java.util.LinkedHash

2019-01-13 17:37发布

I'm getting below error:

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

with below 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() + "/users")
    .as(ArrayList.class);
assertThat(account.get(0).getId()).isEqualTo(expectedId);

Is there a reason why I cannot do get(0)?

5条回答
一纸荒年 Trace。
2楼-- · 2019-01-13 18:02

The issue's coming from Jackson. When it doesn't have enough information on what class to deserialize to, it uses LinkedHashMap.

Since you're not informing Jackson of the element type of your ArrayList, it doesn't know that you want to deserialize into an ArrayList of Accounts. So it falls back to the default.

Instead, you could probably use as(JsonNode.class), and then deal with the ObjectMapper in a richer manner than rest-assured allows. Something like this:

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);
查看更多
别忘想泡老子
3楼-- · 2019-01-13 18:03

The way I could mitigate the JSON Array to collection of LinkedHashMap objects problem was by using CollectionType rather than a TypeReference . This is what I did and worked:

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

Using the TypeReference, I was still getting an ArrayList of LinkedHashMaps, i.e. does not work:

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;
}
查看更多
可以哭但决不认输i
4楼-- · 2019-01-13 18:10

Try the following:

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

or:

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

See conversion of LinkedHashMap for more information.

查看更多
Rolldiameter
5楼-- · 2019-01-13 18:14

I had a similar exception (but different problem) - java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to org.bson.Document , and fortunately it's solved easier:

Instead of

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

which gives error on second line, One can use

List<Document> docs = obj.get("documents");
Document doc = new Document(docs.get(0));
查看更多
再贱就再见
6楼-- · 2019-01-13 18:17

I have this method for deserializing an XML and converting the 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 );   
}

and this is the call:

List<POJO> pojos = (List<POJO>) MyUtilClass.deserialize(xml, ArrayList.class,new TypeReference< List< POJO >>(){ });
查看更多
登录 后发表回答