介紹
作爲移動端開發者,和服務器的通信是少不了了。下面我總結一我在開發中遇到有關json的問題
一般的Json
在我剛入門的時候,在公司的寫代碼當時的網絡返回也不復雜,10個字段以內,基本上熟悉Json的固定格式,手動寫Bean接收數據,只要用心字段名稱和類型對應就不會出問題。
推薦的Json格式校驗網站,http://json.parser.online.fr/
問題:就是如果字段複雜,就要花很多時間去校對字段,確認字段對象類型。
解決辦法
其實校驗Json格式這種沒什麼技術含量的事情,應該交給計算機去做。
所以網上有很多解決辦法
在線解析生成Bean對象
網站在這裏: http://www.bejson.com/json2javapojo/
GsonFormat插件
這是個一個能夠直接在Android Studio運行的插件。輸入Json字符串能夠直接生成bean對象
- 安裝
安裝如下圖:
選擇 Plugins->搜索GsonFormat
使用
快捷鍵 Alt+Instert 彈出
複製Json字符串進去就OK了。不定格式的Json
最近在寫個項目,接口來自其他公司網絡返回,有一個巨坑的問題,
不定格式的Json內容。有時是
avatar:{"對象類型"}
- 有時是
avatar:"String類型"
- 其實就一個關鍵的url頭像地址最重要。如果是對象類型,對象中就包含一些圖片信息和url地址,如果是String類型就直接是一個url圖片地址。
直接使用定義爲對象的話就會出現異常
異常信息:參數異常,需要的解析的Bean該字段對應的是Object對象,但Json字符串中對應的是String對象。
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 14210 path $.pin.repins[1].user.avatar
非常非常的坑爹!!
思考
- 從Json解析之後的Bean對象處理是不行的,因爲一開始的解析就報錯。
- 想從Gson解析上看看有什麼特別的功能,從文檔上看沒有有效的解決辦法。有人找到的給個提示。
最終的解決辦法
正則表達式
在網絡數據還沒解析成Bean對象之前,處理成字符串,用正則對該字符串進行處理。
正則表達式,在網絡返回後將二進制流時轉換成字符串,正則表達式匹配查找取出其中url關鍵數據,替換統一成
avatar:"String類型"
下面貼一部分實現代碼
說明:我的網絡訪問使用的是Retrofit,是Jack大神開發的REST風格的網絡訪問框架。以下代碼關鍵是在retrofit.Converter.Factory上得到二進制網絡返回體上做修改,其他網絡框架也可以,只要能到網絡訪問體即可。
網絡字節流轉字符串
@Override
public T convert(ResponseBody value) throws IOException {
Reader reader = value.charStream();//取出字節流
String result;
try {
BufferedReader in = new BufferedReader(reader);//讀取
StringBuffer buffer = new StringBuffer();//構造buffer對象用於拼接
String line;
while ((line = in.readLine()) != null) {//讀行
buffer.append(line);//寫入buffer
}
result = buffer.toString();
} finally {
Utils.closeQuietly(reader);//記得關閉流
}
return gson.fromJson(regexChange(result), type);//返回解析後的對象
}
正則表達式在Java的應用
/**
* 對輸入的字符串進行處理
* @param input 傳入的需要處理的字符串
* @return
*/
private String regexChange(String input) {
String result=input;
//匹配規則是當avatar是{}包裝的對象
Pattern mPAvatar=Pattern.compile("\"avatar\":\\{([^\\}]*)\\}");
Matcher mMAvatar=mPAvatar.matcher(result);
while (mMAvatar.find()){//如果找到 開始替換
result=result.replaceFirst("\"avatar\":\\{([^\\}]*)\\}",getKey(mMAvatar.group()));
}
return result;
}
/**
* 取出關鍵值返回
* @param group
* @return
*/
private String getKey(String group) {
Matcher matcher=mPkey.matcher(group);
StringBuffer buffer=new StringBuffer();
buffer.append("\"avatar\":\"http:///");
while (matcher.find()){
buffer.append(matcher.group(1));
}
buffer.append("\"");
return buffer.toString();
}
完美解決~~
另一種解決辦法
這在是一篇博客看到的,也是在Retrofit上應對不定格式的Json格式解析,思路也是在也是Converter.Factory的convert方法上做處理。思路是定義兩個不同的Bean類型,捕捉異常,做二次解析。不符合我的項目使用,只做介紹。
具體實現看博客:http://blog.csdn.net/efan006/article/details/50544204
總結
- 以上就是我對Json在Android編程中的一些理解和實際應用。
- 運用工具快速開發,把時間花在業務邏輯處理而不是重複的勞動。
- 對問題能夠換語言環境理解思考解決問題。