前言:最近使用 fastjson 解析JSON数据报错:“java.lang.ClassCastException: com.alibaba.fastjson.JSONObject cannot be cast to xx”,在此记录分享一下
报错信息
java.lang.ClassCastException: com.alibaba.fastjson.JSONObject cannot be cast to cn.zhuzicc.springboot.module.StudentEntity
at cn.zhuzicc.springboot.SpringbootApplicationTests.testConsumer(SpringbootApplicationTests.java:50)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
...
场景模拟
BinLogMessage.java
实体对象:
@Data
public class BinLogMessage<T> {
/**
* 更新后数据
*/
private T after;
/**
* 更新前数据
*/
private T before;
/**
* 表名
*/
private String table;
/**
* schema
*/
private String schema;
/**
* 操作类型
*/
private String opType;
/**
* 时间
*/
private String when;
}
StudentEntity.java
实体对象:
@Data
public class StudentEntity {
/**
* 姓名
*/
private String name;
/**
* 年龄
*/
private Integer age;
/**
* 生日
*/
private Date birthday;
}
测试方法:
@Test
public void testConsumer() {
// 模拟消息
String message = "{\n" +
" \"before\":{\n" +
" \"name\":\"张三\",\n" +
" \"age\":\"27\",\n" +
" \"birthday\":\"1996-02-03\"\n" +
" },\n" +
" \"after\":{\n" +
" \"name\":\"张三\",\n" +
" \"age\":\"29\",\n" +
" \"birthday\":\"1994-02-03\"\n" +
" },\n" +
" \"table\":\"testDB\",\n" +
" \"schema\":\"mysql-bin.000355\",\n" +
" \"opType\":\"471265bb-7bf3-11e7-b7a3-005056ab45e1:254438046\",\n" +
" \"when\":\"471265bb-7bf3-11e7-b7a3-005056ab45e1:254438046\"\n" +
"}";
BinLogMessage<StudentEntity> binLogMessage = JSONObject.parseObject(message, BinLogMessage.class);
StudentEntity after = binLogMessage.getAfter();
StudentEntity before = binLogMessage.getBefore();
}
运行结果:
问题原因
正常使用 JSONObject.parseObject()
解析 JSON
对象是不会报错的,但是如果解析后的实体类中包含泛型< T>对象,就会如同上述示例一样,在获取泛型< T>对象时转换报错;
因为 fastjson
在解析 JSON
数据时,如果涉及到泛型< T>对象,就无法完成泛型< T>对象的解析,而是解析拿到一个 JSONObject
对象,而不是传入的泛型对象,就如下图:
解决办法
针对这种情况, fastjson
提供了一个重载方法 :
public static <T> T parseObject(String text, TypeReference<T> type, Feature... features) {
return parseObject(text, type.type, ParserConfig.global, DEFAULT_PARSER_FEATURE, features);
}
使用示例:
public void testConsumer() {
/*
*...省略
*/
BinLogMessage<StudentEntity> binLogMessage = JSONObject.parseObject(message, new TypeReference<BinLogMessage<StudentEntity>>() {
});
StudentEntity after = binLogMessage.getAfter();
StudentEntity before = binLogMessage.getBefore();
System.out.println("after:" + after.toString());
System.out.println("before:" + before.toString());
}
输出结果:
看看解析对象:
JSON示例数据
需要测试的自取哈
{
"before":{
"name":"张三",
"age":"27",
"birthday":"1996-02-03"
},
"after":{
"name":"张三",
"age":"29",
"birthday":"1994-02-03"
},
"table":"testDB",
"schema":"mysql-bin.000355",
"opType":"471265bb-7bf3-11e7-b7a3-005056ab45e1:254438046",
"when":"471265bb-7bf3-11e7-b7a3-005056ab45e1:254438046"
}
感 谢
各 位
大 佬
的 阅
读,随
手 点
赞,日
薪 过
万~!
!!