天天看點

FastJson TypeReference 緩存

一直用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

版權聲明:本文為部落客原創文章,轉載請附上博文連結!