[java] java.lang.ClassCastException : java.util.LinkedHashMap을 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
.
Jackson에의 요소 유형을 알리지 않았기 때문에 ArrayList
으로 deserialize하려는 것을 알지 못합니다.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);
답변
다음을 시도하십시오.
POJO pojo = mapper.convertValue(singleObject, POJO.class);
또는:
List<POJO> pojos = mapper.convertValue(
listOfObjects,
new TypeReference<List<POJO>>() { });
자세한 내용 은 LinkedHashMap 변환 을 참조하십시오.
답변
LinkedHashMap 개체의 수집 문제에 대한 JSON 배열을 완화 할 수있는 방법 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)
두 번째 줄에 오류가 발생하면 One 사용할 수 있습니다.
List<Document> docs = obj.get("documents");
Document doc = new Document(docs.get(0));
답변
일반적인 두 가지 방법으로 문제 해결
- 유형은 객체입니다.
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;
}
- 유형은 컬렉션 랩 개체입니다.
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을 deserialize하고 형식을 변환하는이 메서드가 있습니다.
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 클래스를로드 할 수없고 convertJson
jackson이 작업을 수행하도록 프로젝트 B의 메서드 를 재정의하기 때문에 발생합니다.
public class ServiceAImpl extends ServiceA<Account> {
@Override
public DocSearchResponse<T> convertJson(String result){
return mapper.readValue(result, new TypeReference<DocSearchResponse<T>>() {});
}
}
}