1. 程式人生 > >JSON的使用、利用正則表示式解決不定型別返回Json格式

JSON的使用、利用正則表示式解決不定型別返回Json格式

介紹

作為移動端開發者,和伺服器的通訊是少不了了。下面我總結一我在開發中遇到有關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 彈出GsonFormat
    複製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

總結

  1. 以上就是我對Json在Android程式設計中的一些理解和實際應用。
  2. 運用工具快速開發,把時間花在業務邏輯處理而不是重複的勞動。
  3. 對問題能夠換語言環境理解思考解決問題。
(function () { ('pre.prettyprint code').each(function () { var lines = (this).text().split(  \n  ).length;var  numbering = $('
    ').addClass('pre-numbering').hide(); (this).addClass(  hasnumbering  ).parent().append(  numbering); for (i = 1; i

介紹

作為移動端開發者,和伺服器的通訊是少不了了。下面我總結一我在開發中遇到有關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 彈出GsonFormat
    複製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

總結

  1. 以上就是我對Json在Android程式設計中的一些理解和實際應用。
  2. 運用工具快速開發,把時間花在業務邏輯處理而不是重複的勞動。
  3. 對問題能夠換語言環境理解思考解決問題。
(function () { ('pre.prettyprint code').each(function () { var lines = (this).text().split(  \n  ).length;var  numbering = $('
    ').addClass('pre-numbering').hide(); (this).addClass(  hasnumbering  ).parent().append(  numbering); for (i = 1; i