一直用FastJson 做rest接口的序列化,FastJson對泛型的支援也非常好。經過一段時間使用後發現不定時的會報JsonObject can’t covert to ****的錯誤,但是重新開機之後就好了。排查過程不贅述,直接上代碼示範
String itemJsonStr = "{\"models\":{\"_defaultModel\":{\"id\":824,\"itemName\":\"【特惠】花王L54尿不濕\",\"itemStatus\":1,\"itemPrice\":null,\"itemStock\":1511,\"categoryId\":\"69aefe645dc0482dbced7a234f71e0a9\",\"brandId\":\"e096294ba3db4703972f26ce82d64692\",\"expand\":null,\"ytItemNo\":\"MDJPHW-L54TH\",\"remarks\":\"\",\"locality\":\"日本\",\"spec\":\"包裝\",\"pictures\":[\"http://staticonline.hipac.cn/item/201511/11231324205997.jpg\",\"http://staticonline.hipac.cn/item/201511/11231324204657.jpg\"],\"otherPictures\":[\"http://staticonline.hipac.cn/item/201511/11231324200849.jpg\"],\"itemDescribe\":\"偏遠地區不發貨。日本銷量No.1紙尿褲品牌,日本原裝進口,海關監管,保稅區直供!專利凹凸網狀織物表面,3倍透氣,牢牢鎖住稀軟便便,讓小屁屁持久幹爽舒适。表層纖維添加天然植物精華,溫柔呵護寶寶嬌嫩肌膚。适合體重在9-14kg的寶寶。\",\"netPrice\":null,\"transitFee\":null,\"minPrice\":0.1,\"taxRate\":0.1,\"taxAmount\":null,\"guidePrice\":null,\"specificationTOs\":[],\"createTime\":1448256261000,\"editTime\":1451300191000,\"itemChannel\":\"0\",\"specialShopId\":\"0\",\"prompt\":\"\",\"keyWord\":\"每周特惠,花王,L54,尿不濕\"}},\"message\":\"\",\"code\":\"200\",\"totalCount\":0,\"success\":true,\"defaultModel\":{\"id\":824,\"itemName\":\"【特惠】花王L54尿不濕\",\"itemStatus\":1,\"itemPrice\":null,\"itemStock\":1511,\"categoryId\":\"69aefe645dc0482dbced7a234f71e0a9\",\"brandId\":\"e096294ba3db4703972f26ce82d64692\",\"expand\":null,\"ytItemNo\":\"MDJPHW-L54TH\",\"remarks\":\"\",\"locality\":\"日本\",\"spec\":\"包裝\",\"pictures\":[\"http://staticonline.hipac.cn/item/201511/11231324205997.jpg\",\"http://staticonline.hipac.cn/item/201511/11231324204657.jpg\"],\"otherPictures\":[\"http://staticonline.hipac.cn/item/201511/11231324200849.jpg\"],\"itemDescribe\":\"偏遠地區不發貨。日本銷量No.1紙尿褲品牌,日本原裝進口,海關監管,保稅區直供!專利凹凸網狀織物表面,3倍透氣,牢牢鎖住稀軟便便,讓小屁屁持久幹爽舒适。表層纖維添加天然植物精華,溫柔呵護寶寶嬌嫩肌膚。适合體重在9-14kg的寶寶。\",\"netPrice\":null,\"transitFee\":null,\"minPrice\":0.1,\"taxRate\":0.1,\"taxAmount\":null,\"guidePrice\":null,\"specificationTOs\":[],\"createTime\":1448256261000,\"editTime\":1451300191000,\"itemChannel\":\"0\",\"specialShopId\":\"0\",\"prompt\":\"\",\"keyWord\":\"每周特惠,花王,L54,尿不濕\"}}";
//下面這行注釋掉第二列印出來就是true
ResultData<?> resultFromClass = JSONObject.parseObject(itemJsonStr, new TypeReference<ResultData>() {
});
System.out.println(resultFromClass.getDefaultModel() instanceof JSONObject);
ResultData<?> itemResult = JSONObject.parseObject(itemJsonStr, new TypeReference<ResultData<ItemTO>>() {}.getType());
System.out.println(itemResult.getDefaultModel() instanceof ItemTO);
這樣列印出來的結果是true,false。但是把第一個parseObject 注釋掉,第二個就列印出true。大緻debug了下FastJson的代碼,大概定位到問題應該是出現對類解析的緩存上
ParserConfig.java,getDeserializer方法
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);
}
}
第一個if 判斷是否是class,第二個if是判斷是否泛型類型,getRawType 是擷取泛型的類型,然後進入getDeserializer 方法,這個方法裡有一個緩存
if (type instanceof WildcardType || type instanceof TypeVariable || type instanceof ParameterizedType) {
derializer = derializers.get(clazz);
}
緩存的放入是在putDeserializer 這個方法
public void putDeserializer(Type type, ObjectDeserializer deserializer) {
derializers.put(type, deserializer);
}
可以看到緩存的key是Type.
由此引發的問題:首先解析new TypeReference() ,走了getDeserializer 的第一個if,這樣putDeserializer方法裡放入的是ResultData。接着解析new TypeReference<ResultData>(),這個時候走了getDeserializer 的第二個if,結果rawType是ResultData,是以直接從緩存中傳回了第一次解析的結果。這樣就相當于丢失了泛型類型ItemTO,導緻最後類型轉換失敗。使用中偶現的原因是大部分ResultData都有泛型,隻有非常少的ResultData沒有泛型,是以當調用了沒有泛型的ResultData之後,就會出現錯誤。
解決方案:統一使用泛型類型,項目中不允許沒有泛型類型的ResultData,就不會存在這個問題。
我現在的解決方案是 jar包上最新的jar就可以了…人家修複了
作者:ykdsg
來源:CSDN
原文:https://blog.csdn.net/ykdsg/article/details/50432494
版權聲明:本文為部落客原創文章,轉載請附上博文連結!