背景
有一个实体类 User:
public class User {
private String id;
private String name;
private String age;
}
后端调用其他服务的接口,得到的响应 response 是这样的:
{
"success": true,
"data": [
{"id": 1, "name": "张三", "age": "16"},
{"id": 2, "name": "李四", "age": "17"},
{"id": 3, "name": "王五", "age": "18"}
],
"message": null,
"errorCode": 200
}
现在需要从响应里解析出 data 里的 id
和 name
字段。写法如下:
List<User> userList = (List<User>) response.getData();
Map<String, String> map = userList.stream().collect(Collectors.toMap(e -> e.getId(), e -> e.getName()));
结果报错了!报错信息:java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to User
原因
通过打断点调试,可以发现得到的 List<User>
里的元素类型并不是 User 实体类,而是 LinkedHashMap
。
为什么我们已经用 List<User>
来声明了,结果得到的 List 里的元素类型却是 LinkedHashMap
呢?
主要是因为我们要用的对象没有在本地形成类型强引用,JVM没办法将当前对象关联到字节码文件。
所以,只需要将这个对象先转为JSON字符串,然后通过JSON工具转为对象就行。
解决方法
第一种做法:TypeReference
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
ObjectMapper mapper = new ObjectMapper();
List<User> userList= mapper.convertValue(response.getData(), new TypeReference<List<User>>(){});
Map<String, String> map = userList.stream().collect(Collectors.toMap(e -> e.getId(), e -> e.getName()));
如果 data 里的数据没有对应的实体类,也可以这样:
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
ObjectMapper mapper = new ObjectMapper();
List<JSONObject> userList= mapper.convertValue(response.getData(), new TypeReference<List<JSONObject>>(){});
Map<String, String> map = userList.stream().collect(Collectors.toMap(e -> e.getString("id"), e -> e.getString("name")));
第二种做法:JavaType
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
ObjectMapper mapper = new ObjectMapper();
// 排除json字符串中实体类没有的字段
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
JavaType javaType = mapper.getTypeFactory().constructCollectionType(ArrayList.class, JSONObject.class);
List<JSONObject> userList = mapper.readValue(response.getData(), javaType);
附
需要用到的工具包的依赖:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.38</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
<version>1.5.1.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>1.5.1.RELEASE</version>
</dependency>