Fastjson解析多级泛型时⽽失败的解决⽅案fastjson 解析多级泛型时⽽失败:
平时运⾏好好的,偶尔会反序列化泛型失败(实际是被转化成了JSONObject),堆栈如下
java.lang.ClassCastException: com.alibaba.fastjson.JSONObject cannot be cast to com.mljr.hr.bean.Position
at com.mljr.hr.task.PositionSyncTask.batchNewData(PositionSyncTask.java:66)
at com.mljr.hr.task.AbstractScheduleTask.startScheduleNewData(AbstractScheduleTask.java:66)
at com.mljr.hr.task.PositionSyncTask.scheduleNewData(PositionSyncTask.java:56)
at com.mljr.hr.task.PositionSyncTask$$FastClassBySpringCGLIB$$b4e853c8.invoke()
at lib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:720)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocati
on.java:157)
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:85) at com.github.blackshadowwalker.spring.distributelock.interceptor.LockAspectSupport$1.invoke(LockAspectSupport.java:46)
at com.github.blackshadowwalker.spring.distributelock.ute(LockAspectSupport.java:89)
at com.github.blackshadowwalker.spring.distributelock.ute(LockAspectSupport.java:73)
at com.github.blackshadowwalker.spring.distributelock.interceptor.LockAspectSupport.around(LockAspectSupport.java:52)
flect.NativeMethodAccessorImpl.invoke0(Native Method)
flect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
flect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at flect.Method.invoke(Method.java:483)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
外包装对象定义
class MyResponse<T> {
Boolean success;
Integer errCode;
String errDes;
T result;
}
1
2
3
4
5
6
7
声明:MyResponse<List<Dept>>
⼀、调试跟踪
调试分析
经过多次调试,问题出现在这⾥ DefaultFieldDeserializer#parseField
@Override
public void parseField(DefaultJSONParser parser, Object object, Type objectType, Map<String, Object> fieldValues) {
if (fieldValueDeserilizer == null) {
Config());
}
if (objectType instanceof ParameterizedType) {
ParseContext objContext = Context();
fieldType = FieldType(this.clazz, objectType, fieldType);
}
1
2
3
4
5
6
7
8
9
10
11
如我的对象类型 result 的类型是 List, 但是经过 Config()) 的处理后 fieldValueDeserilizer ==JavaObjectDeserializer, 然后在 68⾏ 进⾏解析处理
68 value = fieldValueDeserilizer.deserialze(parser, fieldType, fieldInfo.name);
1
接着分析 JavaObjectDeserializer
public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
if (type instanceof GenericArrayType) {
Type componentType = ((GenericArrayType) type).getGenericComponentType();
if (componentType instanceof TypeVariable) {
TypeVariable<?> componentVar = (TypeVariable<?>) componentType;
componentType = Bounds()[0];
}
List<Object> list = new ArrayList<Object>();
parser.parseArray(componentType, list);
Class<?> componentClass;
if (componentType instanceof Class) {
componentClass = (Class<?>) componentType;
Object[] array = (Object[]) wInstance(componentClass, list.size());
return (T) array;
} else {
return (T) Array();
}
}
if (type instanceof Class && type != Object.class && type != Serializable.class) {
return (T) parser.parseObject(type);
}
return (T) parser.parse(fieldName);//最后到了这⾥,
//⽽ parser == DefaultJSONParser (来源于 `DefaultJSONParser (614) return (T) derializer.deserialze(this, type, fieldName);`) }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
然后进⼊ DefaultJSONParser 1280 ⾏ parse(Object fieldName) ,在这⾥就将result的值解析成了 JSONArray对象,从⽽造成类型转换错误,没有得到预期的类型。
解决⽅案:
回到来这⾥ DefaultFieldDeserializer#parseField
@Override
public void parseField(DefaultJSONParser parser, Object object, Type objectType, Map<String, Object> fieldValues) {
if (fieldValueDeserilizer == null) {
Config());
}
if (objectType instanceof ParameterizedType) {
ParseContext objContext = Context();
fieldType = FieldType(this.clazz, objectType, fieldType);
}
1
2
3
4
5
6
7
8
9
10
11
既然是多级泛型 ParameterizedType 并且解析除了泛型类型 fieldType ,为什么不加⼀⾏
fieldValueDeserilizer = Config().getDeserializer(fieldType)
1
这样从我贴的数据中就得到了 fieldValueDeserilizer = CollectionCodec,这样就根据 fieldType获取到了正确的 fieldValueDeserilizer ⼆、复现
1. 复现
error parse new过程:
1.定义
mType1 = new TypeReference<MyResponse<List>>() {}.getType();
mType2 = new TypeReference<MyResponse<List<Dept>>>() {}.getType();
class MyResponse<T> {
Boolean success;
Integer errCode;
String errDes;
T result;
}
1
2
3
4
5
6
7
8
9
10
2.第⼀次调⽤
使⽤mType1
反序列化使⽤MyResponse<List>,
JSON.parseObject(jsonData, mType1, configBug569, featureValues,
features != null ? features : EMPTY_SERIALIZER_FEATURES);
1
2
结果:Result().getClass()==JSONArray.class,同时fastjson会缓存 MyResponse的解析器(即⽬的类型为JSONArray) 3.第⼆次调⽤
使⽤mType2
反序列化使⽤的 MyResponse<List<Dept>>
JSON.parseObject(jsonData, mType2, configBug569, featureValues, features != null ? features : EMPTY_SERIALIZER_FEATURES);
1
结果:Result().getClass()==JSONArray.class,与期望的List<Dept>不相符
2.分析
第⼀次调⽤反序列化,关键点: ParserConfig(460)
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论