java.lang.ClassCastException:java.util.LinkedHashMap无法强制转换为com.testing.models.Account

时间:2015-03-03 00:02:11

标签: java jackson rest-assured

我收到以下错误:

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

以下代码

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

我有没有理由不能get(0)

8 个答案:

答案 0 :(得分:60)

这个问题来自杰克逊。如果没有关于要反序列化的类的足够信息,则使用LinkedHashMap

由于您未通知杰克逊您ArrayList的元素类型,因此您不知道您要反序列化为ArrayList Account个。所以它回归到默认值。

相反,您可以使用as(JsonNode.class),然后以比保证允许的更丰富的方式处理ObjectMapper。像这样:

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

答案 1 :(得分:24)

尝试以下方法:

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

或:

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

有关详细信息,请参阅conversion of LinkedHashMap

答案 2 :(得分:15)

我可以使用CollectionType而不是TypeReference来缓解 JSON数组以收集LinkedHashMap对象的问题。 这就是我所做的和工作

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

使用TypeReference,我仍然得到LinkedHashMaps的ArrayList,即不起作用

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

答案 3 :(得分:4)

我有一个类似的例外(但问题不同) - java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to org.bson.Document,幸运的是它更容易解决:

而不是

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

在第二行给出错误,可以使用

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

答案 4 :(得分:1)

解决常见的两种方法解析问题

  1. 类型是一个对象
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;
    }
  1. 类型是集合包装对象
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;
}

答案 5 :(得分:0)

我有这种反序列化XML并转换类型的方法:

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

这是电话:

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

答案 6 :(得分:0)

使用杰克逊将字符串映射到具体类时,尤其是在使用泛型类型时。那么可能由于不同的类加载器而发生此问题。我在下面的情景分析器中遇到了一次:

项目B取决于图书馆A

在库A中:

public class DocSearchResponse<T> {
 private T data;
}

它具有从外部源查询数据并使用jackson转换为具体类的服务

public class ServiceA<T>{
  @Autowired
  private ObjectMapper mapper;
  @Autowired
  private ClientDocSearch searchClient;

  public DocSearchResponse<T> query(Criteria criteria){
      String resultInString = searchClient.search(criteria);
      return convertJson(resultInString)
  }
}

public DocSearchResponse<T> convertJson(String result){
     return mapper.readValue(result, new TypeReference<DocSearchResponse<T>>() {});
  }
}

在项目B中:

public class Account{
 private String name;
 //come with other attributes
}

我使用库中的ServiceA进行查询并转换数据

public class ServiceAImpl extends ServiceA<Account> {
    
}

并利用它

public class MakingAccountService {
    @Autowired
    private ServiceA service;
    public void execute(Criteria criteria){
      
        DocSearchResponse<Account> result = service.query(criteria);
        Account acc = result.getData(); //  java.util.LinkedHashMap cannot be cast to com.testing.models.Account
    }
}

之所以发生这种情况,是因为杰克逊无法从LibraryA的类加载器中加载帐户类,而只是在项目B中覆盖方法convertJson以让杰克逊完成工作

public class ServiceAImpl extends ServiceA<Account> {
        @Override
        public DocSearchResponse<T> convertJson(String result){
         return mapper.readValue(result, new TypeReference<DocSearchResponse<T>>() {});
      }
    }
 }

答案 7 :(得分:0)

这是我在我的项目中使用的东西,返回了 Json 对象,我将其转换为 POJO 列表,然后访问该元素。 我从另一个微服务中获取了 Json 对象的输入。

主要是:- JsonNode stock = 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;
    }