情况说明:springcloud项目通过feign调用远程接口,无法得到想要的实体类。
服务方返回List<SkuHasStockVo>集合:
调用方接收返回,发现变成了LinkedHashMap类型,
于是下面的代码执行,进行类型转换的时候,会抛出ClassCastException异常。
造成原因:
断点进入feign底层调用服务代码,调用栈和大致说明见下图:
通过上图可以知道,feign底层将response的实体转换成LinkedHashMap。
那为什么要转成LinkedHashMap,可以参考这篇博客。
内容引自:https://blog.csdn.net/hp_yangpeng/article/details/80592332
解决方法:
要想得到目标实体SkuHasStockVo实体,需要将 list数据再序列化-反序列化一次。
调用FeignUtil.formatListClass方法即可。
工具类如下:
import com.google.common.base.Strings;
import com.leicx.guli.common.exception.RRException;
import java.util.ArrayList;
import java.util.List;
/**
* @author daxiong
* @date 2021/8/16 下午10:15
*/
public class FeignUtil {
public static <T> T formatClass(R r, Class<T> tClass) {
String jsonString = getResultJson(r);
if (Strings.isNullOrEmpty(jsonString)) {
return null;
}
return JsonUtil.parseObject(jsonString, tClass);
}
private static String getResultJson(R r) {
if (!r.success()) {
throw new RRException(r.get("msg").toString());
}
return JsonUtil.toJsonString(r.get("data"));
}
public static <T> List<T> formatListClass(R r, Class<T> tClass) {
String jsonString = getResultJson(r);
if (Strings.isNullOrEmpty(jsonString)) {
return new ArrayList<>();
}
return JsonUtil.parseList(jsonString, tClass);
}
}
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.util.List;
/**
* @author daxiong
* @date 2021/8/16 下午10:12
*/
@Slf4j
public class JsonUtil {
static final ObjectMapper objectMapper = new ObjectMapper();
public static <T> T parseObject(String jsonStr, Class<T> tClass) {
try {
return objectMapper.readValue(jsonStr, tClass);
} catch (IOException e) {
log.error(e.getMessage());
return null;
}
}
public static <T> List<T> parseList(String text, Class<T> clazz) {
JavaType javaType = objectMapper.getTypeFactory().constructCollectionType(List.class, clazz);
try {
return objectMapper.readValue(text, javaType);
} catch (IOException e) {
log.error(e.getMessage());
return null;
}
}
/**
* json序列化
*
* @param obj 需要序列化的对象
* @return
*/
public static String toJsonString(Object obj) {
try {
return objectMapper.writeValueAsString(obj);
} catch (JsonProcessingException e) {
log.error(e.getMessage());
return null;
}
}
}
注意:此处的入参R是我自己的包装返回对象,用的时候需要改一下,改成实际的包装返回对象,或者也可以直接传入String进去。