fastJson遇到的問題


概述

現在的代碼開發中,json這種數據類型使用的是越來越多,因為它的存取速度都比較快,而且,使用起來非常的簡單,今天工作的時候,我就遇到了一個關於json的生產問題,這個問題我之前確實還沒有注意過,這邊記錄下。

問題再現

再一次遠程調用獲取相關信息成功之后,需要解析返回的json對象,這個json里面包含了三個元素,一個key為data的jsonObject,表示業務數據,一個Key為success的String,表示是否成功,一個key為resultMessage的失敗原因。正常情況下,這個data是不可能為空的,但是今天不知道怎么了,遠端返回的結果里面這個data就是空的,所以解析的時候就出現了如下異常:

Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to com.alibaba.fastjson.JSONObject
    at com.alibaba.fastjson.JSONObject.getJSONObject(JSONObject.java:109)
    at com.example.demo.MainTest.main(MainTest.java:10)

 

當然這里要提前說明下,我這邊使用的fastJson的版本是1.2.7,出現上面這個錯是不是很奇怪,正常不應該返回一個null嗎?怎么返回的是String類型不能轉成JSONObject呢?

問題跟蹤

問題到了這個地步還有什么好說的呢?只能模仿生產的返回,一步一步的去解析了。

 1 public class MainTest {
 2     public static void main(String[] args) {
       // 寫一個字符串,模擬生產的返回,其中data的值為空
3 String str = "{\"data\": \"\",\"success\": \"true\",\"resultMessage\": \"成功\"}"; 4 // 序列化成json 5 JSONObject result = JSONObject.parseObject(str);
       // 獲取data的值
6 JSONObject data = result.getJSONObject("data"); 7 8 System.out.println(data); 9 } 10 }

 

通過debug可以得知,第五行代碼是可以正常執行的,返回如下:

{"data":"","success":"true","resultMessage":"成功"}

這個沒有問題,那問題就在第6行代碼上了,我們看一下getJSONObject方法:

1     public JSONObject getJSONObject(String key) {
2         Object value = map.get(key);
3 
4         if (value instanceof JSONObject) {
5             return (JSONObject) value;
6         }
7 
8         return (JSONObject) toJSON(value);
9     }

 

這邊第2行代碼根據key獲取的value是"",這個顯然不是JSONObject類型,直接走最后一行toJSON方法,

 1     public static Object toJSON(Object javaObject, ParserConfig mapping) {
 2         if (javaObject == null) {
 3             return null;
 4         }
 5 
 6         if (javaObject instanceof JSON) {
 7             return javaObject;
 8         }
 9 
10         if (javaObject instanceof Map) {
11             Map<Object, Object> map = (Map<Object, Object>) javaObject;
12 
13             JSONObject json = new JSONObject(map.size());
14 
15             for (Map.Entry<Object, Object> entry : map.entrySet()) {
16                 Object key = entry.getKey();
17                 String jsonKey = TypeUtils.castToString(key);
18                 Object jsonValue = toJSON(entry.getValue());
19                 json.put(jsonKey, jsonValue);
20             }
21 
22             return json;
23         }
24 
25         if (javaObject instanceof Collection) {
26             Collection<Object> collection = (Collection<Object>) javaObject;
27 
28             JSONArray array = new JSONArray(collection.size());
29 
30             for (Object item : collection) {
31                 Object jsonValue = toJSON(item);
32                 array.add(jsonValue);
33             }
34 
35             return array;
36         }
37 
38         Class<?> clazz = javaObject.getClass();
39 
40         if (clazz.isEnum()) {
41             return ((Enum<?>) javaObject).name();
42         }
43 
44         if (clazz.isArray()) {
45             int len = Array.getLength(javaObject);
46 
47             JSONArray array = new JSONArray(len);
48 
49             for (int i = 0; i < len; ++i) {
50                 Object item = Array.get(javaObject, i);
51                 Object jsonValue = toJSON(item);
52                 array.add(jsonValue);
53             }
54 
55             return array;
56         }
57 
58         if (mapping.isPrimitive(clazz)) {
59             return javaObject;
60         }
61 
62         try {
63             List<FieldInfo> getters = TypeUtils.computeGetters(clazz, null);
64 
65             JSONObject json = new JSONObject(getters.size());
66 
67             for (FieldInfo field : getters) {
68                 Object value = field.get(javaObject);
69                 Object jsonValue = toJSON(value);
70 
71                 json.put(field.getName(), jsonValue);
72             }
73 
74             return json;
75         } catch (IllegalAccessException e) {
76             throw new JSONException("toJSON error", e);
77         } catch (InvocationTargetException e) {
78             throw new JSONException("toJSON error", e);
79         }
80     }

 

這個方法有點長,但其實,真正執行了的也就是38行,獲取value對應的class對象,這邊返回的java.lang.String,再就是58到60行,判斷這個對象是不是基礎類型,是就直接返回,那么這邊就返回的"",后面強制類型轉換的時候當然就會報錯。

上面這個問題似乎還不好解決啊,后來看了一下fastJson的幾個高版本,已經解決了這個問題,我們來看一下1.2.51的getJSONObject方法:

 1     public JSONObject getJSONObject(String key) {
 2         Object value = map.get(key);
 3 
 4         if (value instanceof JSONObject) {
 5             return (JSONObject) value;
 6         }
 7 
 8         if (value instanceof String) {
 9             return JSON.parseObject((String) value);
10         }
11 
12         return (JSONObject) toJSON(value);
13     }

 

多了8-10行代碼,針對String做了下處理,直接返回String解析之后的結果,這樣就可以返回理想中的null了。

總結

平時代碼開發過程中,一定要進行異常情況的測試,不能夠想當然,要盡量覆蓋每個分支,要讓代碼跑不崩潰。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM