2015-08-31 77 views
8

我在我的項目中使用Volley來處理網絡請求。下面是一個示例JSON我的服務器返回利用Volley處理響應

JSON對象響應

{"code":"success", "data":{"some data"}} 

JSON陣列響應

{"code":"success", "data":["some data"]} 

當某些驗證錯誤或任何其他誤差時,服務器返回以下響應:

{"code":"failed", "error":"Access denied"} 

問題在於解析數據。當請求成功時,在ResponseListeneronResponse中,我簡單地得到data密鑰的內容。在那裏,我期待的結果與我在上面發佈的結果相同。我不明白爲什麼Volley只返回data的內容而不完成JSON。我以前也用過Volley。但從未遇到過這樣的問題。

解析代碼:成功

private void getOnboardingCategories() { 
    Response.Listener<JSONArray> responseListener = new Response.Listener<JSONArray>() { 

     @Override 
     public void onResponse(JSONArray response) { 
      Log.d(LOG_TAG, "CATEGORY RESPONSE: " + response.toString()); 
      if (response != null) { 
       int dataLength = response.length(); 
       for (int i = 0; i < dataLength; i++) { 
        JSONObject jObject = response.optJSONObject(i); 
        if (jObject != null) { 
         CategoryType2 categoryType2 = new CategoryType2(); 
         categoryType2.set_id(jObject.optString("_id")); 
         categoryType2.setName(jObject.optString("name")); 
         categoryType2.setApp_icon_data(jObject.optString("thumbnail_data")); 
         categories.add(categoryType2); 
        } 
       } 
      } 
      if (isVisible()) 
       sellAdapter.notifyDataSetChanged(); 
     } 
    }; 

    Response.ErrorListener errorListener = new Response.ErrorListener() { 

     @Override 
     public void onErrorResponse(VolleyError error) { 
      error.printStackTrace(); 
      Util.errorHandler(error, ctx); 
     } 
    }; 

    JsonArrayRequest jsonObjectRequest = new JsonArrayRequest(Method.GET, url, 
      null, responseListener, errorListener); 
    MyApplication.getInstance().addToRequestQueue(jsonObjectRequest, "onboarding"); 
} 

響應:

{ 
    code: "success", 
    data: [ 
      { 
       _id: "55c06b05a3e0041a73cea744", 
       name: "Test Category 1", 
       thumbnail_data: "", 
      }, 
      { 
       _id: "55c06b16a3e0046108cea744", 
       name: "Test Category 2", 
       thumbnail_data: "", 
      } 
     ] 
} 

ResponseListeneronResponse,我得到這樣的數據:

[ 
    { 
     _id: "55c06b05a3e0041a73cea744", 
     name: "Test Category 1", 
     thumbnail_data: "", 
    }, 
    { 
     _id: "55c06b16a3e0046108cea744", 
     name: "Test Category 2", 
     thumbnail_data: "", 
    } 
] 

當錯誤發生時,服務器返回此響應:

{"code":"failed", "error":"error_msg"} 

由此,Volley拋出ParseException因爲它期望JSONArray。我需要向用戶顯示錯誤信息。早些時候,我使用AsyncTask,我在那裏處理錯誤。但是,Volley我面臨困難。我看着VolleyError,但沒有得到任何線索。

更新1

private void getOnboardingCategories() { 
    showSpinnerDialog(true); 
    Response.Listener<JSONObject> responseListener = new Response.Listener<JSONObject>() { 

     @Override 
     public void onResponse(JSONObject response) { 
      Log.d(LOG_TAG, "CATEGORY RESPONSE: " + response.toString()); 
      hideSpinnerDialog(); 
      String code = response.optString("code"); 
      if (code.equals("success")) { 
       if (response != null) { 
        JSONArray dataArray = response.optJSONArray("data"); 
        int dataLength = dataArray.length(); 
        for (int i = 0; i < dataLength; i++) { 
         JSONObject jObject = dataArray.optJSONObject(i); 
         if (jObject != null) { 
          CategoryType2 categoryType2 = new CategoryType2(); 
          categoryType2.set_id(jObject.optString("_id")); 
          categoryType2.setName(jObject.optString("name")); 
          categoryType2.setApp_icon_data(jObject.optString("app_icon_data")); 
          categories.add(categoryType2); 
         } 
        } 
       } 
      } 
      if (isVisible()) 
       sellAdapter.notifyDataSetChanged(); 
     } 
    }; 

    Response.ErrorListener errorListener = new Response.ErrorListener() { 

     @Override 
     public void onErrorResponse(VolleyError error) { 
      error.printStackTrace(); 
      Util.errorHandler(error, ctx); 
     } 
    }; 

    JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Method.GET, url, 
      null, responseListener, errorListener); 
    MyApplication.getInstance().addToRequestQueue(jsonObjectRequest, "onboarding"); 
} 

更新 這個問題是不是Volley。服務器端有wrt gzip壓縮問題。我將爲投票結束這個問題。

+0

解析代碼添加 – Nitish

+0

你得到整個響應? 'update1'後仍然有問題嗎? – Blackbelt

+0

嗨..你的update1是什麼? –

回答

5

But, when error occurs, I get Parse exception, when making request for JSONArray

使用JSONObject. has()JSONObject. isNull()檢查哪些鍵存在於解析JSON之前JSON響應。

例如:

JSONObject jsonObject=new JSONObject(<server_response_string>); 
    if(jsonObject.has("data") && !jsonObject.isNull("data")) 
    { 
    // get data JSONArray from response 
    }else{ 
    // get message using error key 
    } 
+0

我應該將JSONArrayRequest更改爲StringRequest,然後處理我的用例。我對嗎? – Nitish

+0

@Nitish:在解析之前,不需要改變在'onResponse'方法內使用'has'和'isNull'。讓我知道如果仍然有任何問題 –

+0

問題是我正在'JsonArrayRequest'。 ResponseListener的'onResponse'只顯示數組的''data''鍵的內容。如果發生錯誤,volley會拋出'ParseError',因爲它期望得到一個'json數組'。我用我的解析代碼更新了我的帖子。請看一看。 – Nitish

1

您可以檢查代碼鍵的值,因爲它總是會提供給您迴應是否會是一個失敗或成功。下面是一個小片段:

JSONObject jObj = new JSONObject(your_response_string); 
if(jObj.getString("code").equalsIgnoreCase("failed")) 
{ 
    //write code for failure.... 
} 
else{ 
     //write code for success...... 
} 

注:更加模塊化的方式來做到這一點是讓一個模型類,並在其中設置你的價值觀。這樣你就可以在一個java對象中獲得所有的值。

+0

是的,我同意,但正如我所說的,在'onResponse'我只獲取'data'的內容。所以我在那裏得到'JSONException'。看到我更新的帖子。 – Nitish

2

通過使用GSON解析JSON值並使用POJO類分配鍵值,可以實現處理這種情況的高效方法。

例子:在兩種情況下,像處理JSONArray或JSONObject的

添加錯誤的情況。請按照以下方式查找您所需的POJO樣品以獲取您的測試數據。

樣品1

public class JSONArrayPojo 
{ 
    private ArrayList<String> data; 

    private String code; 

    private String error; 

    public String getError() { 
     return this.error; 
    } 

    public void setError(String value) { 
     this.error = value; 
    } 

    public ArrayList<String> getData() 
    { 
     return data; 
    } 

    public void setData (ArrayList<String> data) 
    { 
     this.data = data; 
    } 

    public String getCode() 
    { 
     return code; 
    } 

    public void setCode (String code) 
    { 
     this.code = code; 
    } 
} 

樣品2

public class JSONObjectPojo 
{ 
    private String data; 

    private String code; 

    private String error; 

    public String getError() { 
     return this.error; 
    } 

    public void setError(String value) { 
     this.error = value; 
    } 

    public String getData() 
    { 
     return data; 
    } 

    public void setData (String data) 
    { 
     this.data = data; 
    } 

    public String getCode() 
    { 
     return code; 
    } 

    public void setCode (String code) 
    { 
     this.code = code; 
    } 

} 

生成GSON從你的反應和處理了正(成功),並是負面的(錯誤)的情況如下:

@Override 
     public void onResponse(JSONArray response) { 
      Log.d(LOG_TAG, "CCMP CATEGORY RESPONSE: " + response.toString()); 
      if (response != null) { 

//轉換JSON響應轉換GSON格式

   JSONArraryPojo jsonArray = null; 
       GsonBuilder gsonBuilder = new GsonBuilder(); 
       gsonBuilder.serializeNulls(); 
       Gson gson = gsonBuilder.create(); 
       jsonArray = gson.fromJson(response.toString(), JSONArraryPojo.class); 

       if(jsonArray.getCode().equals("success")){ 

        //process your steps if the value is success 
        Toast.makeText(this, jsonArray.getCode(), Toast.LENGTH_SHORT).show(); 

       }else { 
         //displaying toast when error occurs 
         Toast.makeText(this, jsonArray.getError(), Toast.LENGTH_SHORT).show(); 

       } 
      } 

     } 
    }; 

參考鏈接到從解析爲GSON JSON

http://kylewbanks.com/blog/Tutorial-Android-Parsing-JSON-with-GSON

http://examples.javacodegeeks.com/core-java/json/json-parsing-with-gson/

http://www.javacodegeeks.com/2011/01/android-json-parsing-gson-tutorial.html

http://www.mysamplecode.com/2013/07/android-json-stream-data-parsing.html

http://blog.nkdroidsolutions.com/

注:要使用GSON庫的機器人。

添加以下行的gradle中:

compile 'org.immutables:gson:2.1.0.alpha' 
2

更新結果截圖:

成功案例:JSONArray

[ 
    { 
     "_id": "55c06b05a3e0041a73cea744", 
     "name": "Category 1", 
     "thumbnail_data": "" 
    }, 
    { 
     "_id": "55c06b16a3e0046108cea744", 
     "name": "Category 2", 
     "thumbnail_data": "" 
    } 
] 

enter image description here

錯誤案例:JSONObject的

{ 
    "code": "failed", 
    "error": "error_msg" 
} 

enter image description here

在下面我的代碼,注意parseNetworkResponse


以下是我的答案更新,我已經測試爲你提供兩種反應:

 RequestQueue queue = Volley.newRequestQueue(mContext); 
     JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(0, url, new Response.Listener<JSONObject>() { 
      @Override 
      public void onResponse(JSONObject response) { 
       try { 
        if (!response.isNull("success")) { 
         JSONArray jsonArray = response.getJSONArray("success"); 
         Toast.makeText(mContext, "onResponse:\n\n" + jsonArray.toString(5), Toast.LENGTH_SHORT).show(); 
         if (mTextView != null) { 
          mTextView.setText(jsonArray.toString(5)); 
         } 
        } else { 
         String codeValue = response.getString("code"); 
         if ("failed".equals(codeValue)) { 
          String errorMessage = response.getString("error"); 
          Toast.makeText(mContext, "Error Message:\n\n" + errorMessage, Toast.LENGTH_SHORT).show(); 
          if (mTextView != null) { 
           mTextView.setText("Error Message:\n\n" + errorMessage); 
          } 
         } 
        }       
       } catch (JSONException e) { 
        e.printStackTrace(); 
       } 
      } 
     }, new Response.ErrorListener() { 
      @Override 
      public void onErrorResponse(VolleyError error) { 
       Toast.makeText(mContext, "onErrorResponse:\n\n" + error.toString(), Toast.LENGTH_SHORT).show(); 
      } 
     }) { 
      @Override 
      protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) { 
       try { 
        String jsonString = new String(response.data, 
          HttpHeaderParser.parseCharset(response.headers, PROTOCOL_CHARSET)); 
        // Check if it is JSONObject or JSONArray 
        Object json = new JSONTokener(jsonString).nextValue(); 
        JSONObject jsonObject = new JSONObject(); 
        if (json instanceof JSONObject) { 
         jsonObject = (JSONObject) json; 
        } else if (json instanceof JSONArray) { 
         jsonObject.put("success", json); 
        } else { 
         String message = "{\"error\":\"Unknown Error\",\"code\":\"failed\"}"; 
         jsonObject = new JSONObject(message); 
        } 
        return Response.success(jsonObject, 
          HttpHeaderParser.parseCacheHeaders(response)); 
       } catch (UnsupportedEncodingException e) { 
        return Response.error(new ParseError(e)); 
       } catch (JSONException e) { 
        return Response.error(new ParseError(e)); 
       } 
      } 
     }; 

     queue.add(jsonObjectRequest); 

希望這有助於!

+0

@Nitish:我已經更新了我的回答 – BNK

+0

@Nitish:你試過了嗎? – BNK

+0

嗨,你的解決方案給了我如何處理這個問題的想法。但我正在玩弄它,因爲我必須更清晰。我在帖子中發佈了回覆(請參閱**回覆成功**)。當執行達到'onResponse'時,我只得到'json數組'(即數組由'data'引用的數組),而不是完整的響應,這就是爲什麼我不能使用更新中發佈的解決方案,以及這就是爲什麼我在處理錯誤時面臨問題。 – Nitish

1

也許你可以試試這個:
使用FASTJSON庫到您的JSON字符串轉換成Java對象在Response.Listener這樣的: Pojo pojo = JSON.parseObject(response.toString(), Pojo.class);

而且你的POJO的可能是這樣的:

public class Pojo { 
private String code; 
private String error; 
private List<Date> data; 

public String getCode() { 
    return code; 
} 

public void setCode(String code) { 
    this.code = code; 
} 

public String getError() { 
    return error; 
} 

public void setError(String error) { 
    this.error = error; 
} 

public List<Date> getData() { 
    return data; 
} 

public void setData(List<Date> data) { 
    this.data = data; 
} 

public class Data { 
    public String _id; 
    public String name; 
    public String thumbnail_data; 

    public String get_id() { 
     return _id; 
    } 

    public void set_id(String _id) { 
     this._id = _id; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public String getThumbnail_data() { 
     return thumbnail_data; 
    } 

    public void setThumbnail_data(String thumbnail_data) { 
     this.thumbnail_data = thumbnail_data; 
    } 
} 
} 

那麼你需要做的是檢查你的pojo是否有錯誤等值,如果錯誤不爲null,則需要處理它。
fastjson庫幫助您避免轉換時崩潰。

你可以找到FASTJSON here

3

在錯誤的服務器應該返回錯誤JSON,HTTP狀態碼4XX的情況。這就是您設計Restful API的方式。在目前情況下,你的API總是返回2xx,這對應於成功的API結果。 如果您的API發送正確的http響應代碼,在這種情況下,401(未授權)或403(禁止)refer here那麼您的ErrorListener將由Volley調用。您不必在ResponseListener中編寫錯誤響應的解析邏輯。瞭解其他api http狀態代碼,這裏有一個很好的resource

0

使用此代碼:

onResponse(JSONObject response){ 
    if(response.getString("code").equalIgnoreCase("success")){ 
     try{ 
      JSONArray array = response.getJsonArray("data"); 
      //do stuff with array 
     }catch(JSONException e){ 
      JSONObject jsonObject = response.getJsonObject("data"); 
      //do stuff with object 
     } 
    }else{ 
     //show your error here 
    } 
}