之前一直是用Gson做數(shù)據(jù)序列化,后來換工作后新公司是用fastJson做序列化的瘦锹,在做網(wǎng)絡(luò)框架優(yōu)化后,不定時的會拋出JsonObject can't covert to **** 異常,各種排查后發(fā)現(xiàn)是fastJson的問題,下面一步一步來分析:
原始json數(shù)據(jù):
//登錄前
{"code":200,"msg":"成功","data":[]}
//登錄后
{"code":200,"msg":"成功","data":{"count":0}}
解析json代碼:
static CommonResponse responseConvert(String json, Type clz){
JSONObject object = new JSONObject(json);
String data = object.optString(DATA);
if(TextUtils.isEmpty(data) || "[]".equals(data) || "{}".equals(data) ){
CommonResponse resp = JSON.parseObject(json, CommonResponse.class);
....
return resp;
}else{
return JSON.parseObject(json,clz)
}
}
分析原因:
從代碼上來看應(yīng)該沒問題怠苔,看不出什么問題,首先判斷json的data字段是否為空或是否為空數(shù)組仪糖,如果是空則使用默認(rèn)的CommonResponse類去解析嘀略,如果不為空則使用CommonResponse<T>泛型的方式去解析,如果data字段一直為空或一直不為空都不會有問題乓诽,但如果從空變成有數(shù)據(jù)后就出現(xiàn)了上面的異常,通過查看fastJson源碼才發(fā)現(xiàn)問題所在:
ParserConfig.Java
public ObjectDeserializer getDeserializer(Type type) {
...省略無關(guān)代碼
if (type instanceof Class<?>) {
return getDeserializer((Class<?>) type, type);
}
if (type instanceof ParameterizedType) {
Type rawType = ((ParameterizedType) type).getRawType();
if (rawType instanceof Class<?>) {
return getDeserializer((Class<?>) rawType, type);
} else {
return getDeserializer(rawType);
}
}
return JavaObjectDeserializer.instance;
}
通過源碼可以看到咒程,首先判斷參數(shù)type是否為Class鸠天,如果是則進入getDeserializer方法,如果不是則繼續(xù)判斷參數(shù)是否為泛型帐姻,getRawType是獲取泛型類型稠集,如果泛型里面沒有再嵌套泛型了則也進入getDeserializer方法,如果還有則進行遞歸調(diào)用饥瓷,直到拿到最里面泛型為止剥纷,繼續(xù)看getDeserializer方法:
public ObjectDeserializer getDeserializer(Class<?> clazz, Type type) {
...省略無關(guān)代碼
if (type instanceof WildcardType || type instanceof TypeVariable || type instanceof ParameterizedType) {
derializer = derializers.get(clazz);
}
if (derializer != null) {
return derializer;
}
...省略無關(guān)代碼
putDeserializer(type, derializer);
return derializer;
}
在getDeserializer方法中會先去判斷緩存中是否已存儲這個參數(shù)Class如果有則直接用緩存中的,如果沒有則添加到緩存中呢铆。
代碼看到這里也就發(fā)現(xiàn)問題所在了晦鞋,原因:首先在第一次解析CommonResponse的時候走的是getDeserializer的第一個if棺克,然后緩存起來這個CommonResponse悠垛,接著在登錄后,data字段數(shù)據(jù)類型發(fā)生了改變娜谊,變成CommonResponse<T>類型确买,所以解析的走的是第二個if,結(jié)果rawType是CommonResponse纱皆,所以直接從緩存中返回了第一次解析的結(jié)果湾趾,這樣就相當(dāng)于丟失了CommonResponse中的泛型<T>,所以導(dǎo)致最后類型轉(zhuǎn)換失敯派獭!
總結(jié)
統(tǒng)一使用泛型類型搀缠,不允許沒有泛型類型的CommonResponse铛楣,如果不能統(tǒng)一泛型類型的,最好換一個Json解析庫胡嘿!