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)
?
问题来自 Jackson。当它没有关于 class 反序列化的足够信息时,它会使用 LinkedHashMap
。
由于您没有将 ArrayList
的元素类型告知 Jackson,它不知道您要反序列化为 Account
的 ArrayList
。所以它回到默认值。
相反,您可以使用 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);
我有一个类似的异常(但问题不同)- 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));
尝试以下操作:
POJO pojo = mapper.convertValue(singleObject, POJO.class);
或:
List<POJO> pojos = mapper.convertValue(
listOfObjects,
new TypeReference<List<POJO>>() { });
有关详细信息,请参阅 conversion of 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;
}
我有这种反序列化 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 从字符串映射到您的具体 class 时,尤其是在您使用泛型类型时。那么这个问题可能是由于不同的 class 加载程序而发生的。我在下面的场景中遇到过一次:
项目 B 依赖库 A
图书馆 A:
public class DocSearchResponse<T> {
private T data;
}
它有从外部源查询数据的服务,并使用jackson转换为具体class
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
}
}
发生这种情况是因为从 classLibraryA 的加载器,jackson 无法加载帐户 class,然后只需重写项目 B 中的方法 convertJson
让 jackson 完成它的工作
public class ServiceAImpl extends ServiceA<Account> {
@Override
public DocSearchResponse<T> convertJson(String result){
return mapper.readValue(result, new TypeReference<DocSearchResponse<T>>() {});
}
}
}
解决常见的两种方法解析问题
- 类型是对象
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;
}
- With类型是集合包装对象
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;
}
这是我在我的项目中使用的东西,Json 对象被返回,我将它转换为 POJO 列表,然后访问该元素。
我从另一个微服务中获取了 Json 对象的输入。
主要是:-
JsonNode stocks = 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;
}
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>() {});
或
List<Map<String, Object>> responseObj = (List<Map<String, Object>>) response.get("content");
List<LkAuthUserDetail> responseData = ObjectHelper.getObjectMapper().convertValue(responseObj,
new TypeReference<List<LkAuthUserDetail>>() {});
我遇到以下错误:
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)
?
问题来自 Jackson。当它没有关于 class 反序列化的足够信息时,它会使用 LinkedHashMap
。
由于您没有将 ArrayList
的元素类型告知 Jackson,它不知道您要反序列化为 Account
的 ArrayList
。所以它回到默认值。
相反,您可以使用 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);
我有一个类似的异常(但问题不同)- 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));
尝试以下操作:
POJO pojo = mapper.convertValue(singleObject, POJO.class);
或:
List<POJO> pojos = mapper.convertValue(
listOfObjects,
new TypeReference<List<POJO>>() { });
有关详细信息,请参阅 conversion of 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;
}
我有这种反序列化 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 从字符串映射到您的具体 class 时,尤其是在您使用泛型类型时。那么这个问题可能是由于不同的 class 加载程序而发生的。我在下面的场景中遇到过一次:
项目 B 依赖库 A
图书馆 A:
public class DocSearchResponse<T> {
private T data;
}
它有从外部源查询数据的服务,并使用jackson转换为具体class
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
}
}
发生这种情况是因为从 classLibraryA 的加载器,jackson 无法加载帐户 class,然后只需重写项目 B 中的方法 convertJson
让 jackson 完成它的工作
public class ServiceAImpl extends ServiceA<Account> {
@Override
public DocSearchResponse<T> convertJson(String result){
return mapper.readValue(result, new TypeReference<DocSearchResponse<T>>() {});
}
}
}
解决常见的两种方法解析问题
- 类型是对象
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;
}
- With类型是集合包装对象
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;
}
这是我在我的项目中使用的东西,Json 对象被返回,我将它转换为 POJO 列表,然后访问该元素。 我从另一个微服务中获取了 Json 对象的输入。
主要是:-
JsonNode stocks = restTemplate.getForObject("http://localhost:2000/stocks/qty", JsonNode.class);
List>() {});
@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;
}
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>() {});
或
List<Map<String, Object>> responseObj = (List<Map<String, Object>>) response.get("content");
List<LkAuthUserDetail> responseData = ObjectHelper.getObjectMapper().convertValue(responseObj,
new TypeReference<List<LkAuthUserDetail>>() {});