簡體   English   中英

java.lang.ClassCastException:java.util.LinkedHashMap 無法轉換為 com.testing.models.Account

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

我收到以下錯誤:

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)有什么原因嗎?

問題來自傑克遜。 當它沒有關於要反序列化到哪個類的足夠信息時,它使用LinkedHashMap

由於您沒有將ArrayList的元素類型通知 Jackson,因此它不知道您想要反序列化為AccountArrayList 所以它回退到默認值。

相反,您可能可以使用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);

請嘗試以下操作:

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

或者:

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

有關更多信息,請參閱LinkedHashMap 的轉換

我可以減輕JSON 數組到 LinkedHashMap 對象集合問題的方法是使用CollectionType而不是TypeReference 這就是我所做的和工作的

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

我有一個類似的異常(但不同的問題) - 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));

用兩種方法解析共同解決問題

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

我有這種反序列化 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 >>(){ });

當您使用 jackson 從字符串映射到具體類時,尤其是在使用泛型類型時。 那么這個問題可能會因為不同的類加載器而發生。 我遇到過一次以下場景:

項目 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 的類加載器中,jackson 無法加載 Account 類,然后只需覆蓋項目 B 中的方法convertJson即可讓 jackson 完成其工作

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

這是我在我的項目中使用的東西,返回了 Json 對象,我將其轉換為 POJO 列表,然后訪問該元素。 我從另一個微服務中獲取了 Json 對象的輸入。

主要是:- JsonNode stock = restTemplate.getForObject("http://localhost:2000/stocks/qty", JsonNode.class); List<Stock_id_qty> stockList = mapper.convertValue(stocks, new TypeReference<List<Stock_id_qty>>() {});

@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;
    }
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.convertValue(map.get(key), new TypeReference<Account>() {});
public class ObjectHelper { private static ObjectMapper objectMapper = new ObjectMapper(); public static ObjectMapper getObjectMapper() { objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL).configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false); return objectMapper; } }

利用

FetchResponse fetchResponse = ObjectHelper.getObjectMapper().convertValue( data, new TypeReference<FetchResponse>() {});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM