Jackson反序列化泛型注意点
关于Jackson对复杂类型数据反序列化时,泛型对象<T>
被转换为 LinkHashMap
代码如下:
先贴一段测试代码
@Test
public void json(){
String jsonStr = "{"code":0,"subcode":0,"message":"ok","data":{"hostuin":914038622,"encrypt_uin":"NKcPoeoF7w-A","hostname":"YAN","totoal":7,"disslist":[{"diss_name":"QZone背景音乐","diss_cover":"http://y.gtimg.cn/mediastyle/y/img/cover_qzone_130.jpg","song_cnt":5,"listen_num":0,"dirid":205,"tid":0,"dir_show":0},{"diss_name":"搞错了,再来","diss_cover":"http://y.gtimg.cn/music/photo_new/T002R300x300M000000wjiaZ0Q68Vt.jpg?n=1","song_cnt":9,"listen_num":87,"dirid":25,"tid":8445417748,"dir_show":1},{"diss_name":"QQ里的网易云","diss_cover":"http://y.gtimg.cn/music/photo_new/T002R300x300M0000044tjcU3HYRUt.jpg?n=1","song_cnt":7,"listen_num":256,"dirid":23,"tid":8445412062,"dir_show":1},{"diss_name":"哦哦哦哦","diss_cover":"http://y.gtimg.cn/music/photo_new/T002R300x300M0000019DOaT2CE0OG.jpg?n=1","song_cnt":10,"listen_num":94,"dirid":22,"tid":8445391399,"dir_show":1},{"diss_name":"睡觉了","diss_cover":"http://y.gtimg.cn/music/photo_new/T002R300x300M000001HM2km2K4GUv.jpg?n=1","song_cnt":9,"listen_num":29,"dirid":1,"tid":8445382323,"dir_show":1},{"diss_name":"惊艳了时光","diss_cover":"http://qpic.y.qq.com/music_cover/T76450IyeJNdibl3a2PvIRDo2zFwbR8L1g2icGu8GfgxKabkyKTVMveg/300?n=1","song_cnt":11,"listen_num":2227,"dirid":17,"tid":8054843490,"dir_show":1},{"diss_name":"1楼选亚索","diss_cover":"http://qpic.y.qq.com/music_cover/T76450IyeJNdibl3a2PvIRAN81k5hQloWCzsnQNE298kGWfqQG7WCmQ/300?n=1","song_cnt":12,"listen_num":550,"dirid":13,"tid":1436210735,"dir_show":1}]}}";
ApiResp<SongListResp> resp1 = JsonUtil.toResp(jsonStr, new TypeReference<>() {});
ApiResp<SongListResp> resp2 = JsonUtil.toBean(jsonStr, new TypeReference<>() {});
ApiResp<SongListResp> resp3 = JsonUtil.toBean(jsonStr, ApiResp.class);
SongListResp data1 = resp1.getData();
SongListResp data2 = resp2.getData();
SongListResp data3 = resp3.getData();
}
运行结果
可以看到 resp3.data
的 类型是LinkHashMap
而并非指定的 SongListResp
所以 resp3.getData()
将会报错
而 resp1
resp2
则没有这个问题,因为通过new TypeReference<>() {}
指定了泛型类型
resp1
不同点在于 resp2
resp1
是JsonUtil.toResp()
的结果,内部指定了返回类型ApiResp<T>
resp2
是JsonUtil.toBean()
的结果,放回泛型为T
,所以在不做强转的情况下,返回的是Object
Object resp2 = JsonUtil.toBean(jsonStr, new TypeReference<>() {});
# 以下为此处用到的JAVA类
# JsonUtil
@Slf4j
public class JsonUtil {
private static final ObjectMapper OBJECT_MAPPER;
static {
OBJECT_MAPPER = new ObjectMapper();
}
/**
* 装换成一个支持响应的 Resp
* @param jsonStr json字符串
* @param type 想要转换的复杂类型
* @return ApiResp类型为 泛型为 <T> 的对象
* @param <T> 指定泛型
*/
public static <T> ApiResp<T> toResp(String jsonStr,TypeReference<ApiResp<T>> type){
return toBean(jsonStr, type);
}
/**
* 装换成一个复杂 bean
* @param jsonStr json字符串
* @param type 想要转换的复杂类型
* @return 泛型 T 对象
* @param <T> 指定泛型
*/
public static <T> T toBean(String jsonStr,TypeReference<T> type){
Assert.hasText(jsonStr,"序列化字符串不能为空");
try {
return OBJECT_MAPPER.readValue(jsonStr, type);
} catch (JsonProcessingException e) {
log.error("JSON字符串反序列化失败",e);
throw new RuntimeException("JSON字符串反序列化失败");
}
}
/**
* 装换成一个 简单bean
* @param jsonStr json字符串
* @param type 想要转换的Classs
* @return 泛型 T 对象
* @param <T> 指定泛型
*/
public static <T> T toBean(String jsonStr,Class<T> type){
Assert.hasText(jsonStr,"序列化字符串不能为空");
try {
return OBJECT_MAPPER.readValue(jsonStr, type);
} catch (JsonProcessingException e) {
log.error("JSON字符串反序列化失败",e);
throw new RuntimeException("JSON字符串反序列化失败");
}
}
}
# 实体 ApiResp
@Data
@Accessors(chain = true)
@JsonIgnoreProperties(ignoreUnknown = true)
public class ApiResp<T> {
@JsonProperty("code")
private String code;
@JsonProperty("data")
private T data;
}
# 实体 SongListResp
@Data
@Accessors(chain = true)
@JsonIgnoreProperties(ignoreUnknown = true)
public class SongListResp {
@JsonProperty("hostuin")
private String hostuin;
@JsonProperty("disslist")
private List<DisslistDTO> disslist;
@Data
@Accessors(chain = true)
@JsonIgnoreProperties(ignoreUnknown = true)
public static class DisslistDTO {
//以下属性省略
}
}
上次更新: 2024/11/05, 08:29:31