1. 程式人生 > >Android開發中遇到的json解析異常問題

Android開發中遇到的json解析異常問題

Ⅰ.前言

昨天在解析後臺返回的json資料時,json資料一直解析失敗,剛開始以為是kotlin的bean類問題
,因為專案已經逐漸把開發語言從java轉為kotlin,還是第一次使用kotlin寫bean類,但是在將bean類改為java實現後,仍解析失敗。檢視json資料,並沒發現有什麼特殊的地方,之後不斷的除錯,異常不斷出現。最後終於解決了,但卻是經歷了幾個小時的異常,還是決定記錄下,畢竟多總結~才能少採坑.

Ⅱ. json解析

專案中用到的解析框架是JackSon,在解決異常的過程中,有些異常不是很明顯得看出異常原因,其中也懷疑是JackSon框架的問題,之所以懷疑JackSon框架,是因為在該專案的前期開發時,在JackSon踩了多個坑,最後雖然也都解決了,但是卻忘記記錄那些坑。所以在昨天解析不斷異常的時候,也暫時改用手動解析,所以下面除了貼json手動解析的程式碼,也有已經註釋的JackSon程式碼

String script = "javascript:getBookJson();";
    mWebView.evaluateJavascript(script, new ValueCallback<String>() {
                @Override
                public void onReceiveValue(String jsonArray) {

                    if (!TextUtils.equals(jsonArray,"null")){
                        //String jsonArray1 = jsonArray.replace("\\", "");
//jsonArray = jsonArray.substring(1); try { JSONArray jsonArray2 = new JSONArray(jsonArray); int length = jsonArray2.length(); for(int i =0;i<length;i++){ LogUtil.logi("====jsonBean======"
+ jsonArray2.get(i).toString()); } } catch (JSONException e) { e.printStackTrace(); } /* 使用JackSon框架解析的程式碼 List<TestBean> enterpriseBookBeens = JacksonUtil.jsonToBeans(jsonArray, TestBean.class); for (TestBean bean : enterpriseBookBeens) { LogUtil.logi("==bean==" + bean.toString()); }*/ }

上面的程式碼主要是呼叫網頁的JS方法後,返回String型別的資料並且解析. 多餘的程式碼也就不貼了,主要為了記錄下所發生的異常以及原因.

Ⅲ.滿屏的異常

“引起的問題(json手動解析報的異常)

異常資訊:

06-30 18:12:43.631 9301-9301/com.wyk.test W/System.err: org.json.JSONException: Value[{"bookId":"bc557e756d3e41c986898ddad0798d3d" 
...
at org.json.JSON.typeMismatch(JSON.java:111)
at org.json.JSONArray.<init>(JSONArray.java:96)
at org.json.JSONArray.<init>(JSONArray.java:108)
...

原因:返回的資料本來是一個數組,由 [ ] 包括著,但是卻在 [ ] 前後多了兩個”“,那就變成了”[…]”,所以解析也就出現問題,這異常資訊提示是說:資料型別問題,其實點進去異常資訊的Json解析原始碼中,更能看得清楚,主要由於資料並不是JsonArray型別的,所以解析失敗.

怎麼解決:

  • 方法1:後臺生成的資料過濾掉”[…]”的 ” ” 符號後再返回;
  • 方法2:在獲取資料之後,移動端程式碼進行處理,使用jsonArray.substring(1)將” 去除,之後再解析.

\\引起的問題(json手動解析報的異常)

異常資訊:

org.json.JSONException: Expected literal value at character 2 of [{\"bookId\":\"bc557e756d3e41c986898ddad0798d3d\" ...
org.json.JSONTokener.syntaxError(JSONTokener.java:449)
...

原因:由於json中的某些欄位值為String型別的,其中的” “符號都是用\\” \\”這樣的形式來轉義,所以在解析過程中就出現問題了,下面是擷取的json中其中一小段資料, 從log中並沒有看出特殊的,但是輸出到檔案進行檢視,就發現了未經轉義的\\ (這裡也是被轉義成兩個\)

"[\\\"bookId\\\": \\\"bc557e756d3e41c986898ddad0798d3d\\\",\\\"childList\\\": [],\\\"code\\\": \\\"\\\",
    \\\"createTime\\\": 1496805615000,\\\"id\\\": \\\"1103\\\",\\\"isFree\\\": 0,\\\"name\\\": \\\"第一篇\\\
    \t管理篇\\\",\\\"parentId\\\": \\\"0\\\",\\\"sortNo\\\": 2.0,\\\"status\\\": 1,\\\"type\\\": \\\"Section\\\",
    \\\"updateTime\\\": 1496823672000},{\\\"bookId\\\": \\\"bc557e756d3e41c986898ddad0798d3d\\\",
    \\\"childList\\\": [],\\\"code\\\": \\\"\\\",\\\"createTime\\\": 1496805884000,\\\"id\\\": \\\"1104\\\",
    \\\"isFree\\\": 0,\\\"name\\\": \\\"第1章前言\\\",\\\"parentId\\\": \\\"1103\
    \\",\\\"sortNo\\\": 3.0,\\\"status\\\": 1,\\\"type\\\": \\\"Section\\\",\\\"updateTime\\\": 1496823686000}, ...]

怎麼解決

  • 後臺生成的資料過濾掉”\\”的 ” ” 符號再返回;
  • 移動端在獲取資料之後,使用jsonArray.replace(“\\”, “”)進行過濾.

眼花導致的問題

異常資訊

org.json.JSONException: Unterminated string at character 1 of "
06-30 18:40:10.087 5951-5951/com.wyk.test W/System.err:at org.json.JSONTokener.syntaxError(JSONTokener.java:449)
06-30 18:40:10.087 5951-5951/com.wyk.test W/System.err:at org.json.JSONTokener.nextString(JSONTokener.java:228)
06-30 18:40:10.087 5951-5951/com.wyk.test W/System.err:at org.json.JSONTokener.nextValue(JSONTokener.java:107)

原因:由於jsonArray兩邊帶了”[ ]”,移動端對資料進行處理後再解析,jsonArray = jsonArray.substring(jsonArray.length()-1)所導致的,本來我是打算切掉 [ ] 兩邊的”“,但卻寫錯了,所以資料切割後只剩下” , 應該是jsonArray.subString(1,jsonArrray.length-1)才正確

\\引起的問題(JackSon框架解析報的異常)

異常資訊:

com.fasterxml.jackson.databind.JsonMappingException: Unexpected character ('\' (code 92)): was expecting double-quote to start field name
at [Source: [{\"bookId\":\"bc557e756d3e41c986898ddad0798d3d\",\" ...
...

原因:跟上面的原因一樣,資料中多了\, 可JackSon報的異常資訊跟json手動解析報的異常並不一樣

“引起的問題(JackSon框架解析報的異常)

異常資訊

com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.util.ArrayList out of VALUE_STRING token
at [Source: "[{"bookId":"bc557e756d3e41c986898ddad0798d3d","childList":[] ...
at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:873)
at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:869)
...

原因:跟上面的原因一樣,多了”“這符號,異常說不是ArrayList型別,但JackSon報的異常資訊跟json手動解析報的異常並不一樣

ClassCastException異常

異常資訊

java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to com.wyk.test.kotlin.test.TestBean

備註:這是前一專案使用的Gson框架報的異常資訊,在此一併貼上

Ⅳ.總結

  • 之所以將上面相同原因導致的,不一樣的異常資訊列舉出來,主要是為了避免再採坑,就跟避免造輪子同個道理, 前人採坑,後人躲坑;

  • 在開發中,遇到json資料應該留心觀察,才不會因為”“,而花多了時間;

  • 坑多了,那就得記錄下,整理筆記可以讓心情靜下來 .