プロジェクトでネットワークリクエストの処理にVolley
を使用しています。これがサンプルですJSON
私のサーバーが返す
JSONオブジェクトの応答
{"code":"success", "data":{"some data"}}
JSON配列応答
{"code":"success", "data":["some data"]}
検証エラーまたはその他のエラーが発生すると、サーバーは次の応答を返します。
{"code":"failed", "error":"Access denied"}
問題はデータの解析にあります。リクエストが成功すると、onResponse
のResponseListener
で、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: "",
}
]
}
onResponse
のResponseListener
で、次のデータを取得します。
[
{
_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
に関するものではありませんでした。サーバー側のgzip圧縮に問題がありました。私はこの質問を閉じることに投票するつもりです。
しかし、エラーが発生すると、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
}
このような状況を処理する効率的な方法は、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 [〜#〜] from [〜#〜] 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/
注: AndroidでGSONライブラリを利用するため。
Gradleに次の行を追加します。
compile 'org.immutables:gson:2.1.0.alpha'
結果のスクリーンショットを更新:
成功例:JSONArray
[
{
"_id": "55c06b05a3e0041a73cea744",
"name": "Category 1",
"thumbnail_data": ""
},
{
"_id": "55c06b16a3e0046108cea744",
"name": "Category 2",
"thumbnail_data": ""
}
]
エラーケース:JSONObject
{
"code": "failed",
"error": "error_msg"
}
以下の私のコードでは、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);
お役に立てれば!
コードキーの値は、応答が失敗であるか成功であるかを常に利用できるため、確認できます。以下は小さなスニペットです。
JSONObject jObj = new JSONObject(your_response_string);
if(jObj.getString("code").equalsIgnoreCase("failed"))
{
//write code for failure....
}
else{
//write code for success......
}
注:これを行うためのよりモジュール化された方法は、モデルクラスを作成し、それに値を設定することです。この方法では、すべての値を単一のJavaオブジェクトで取得します。
多分あなたはこれを試すことができます:
fastjsonライブラリを使用して、json文字列をResponse.ListenerのJavaオブジェクトに次のように変換します: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を見つけることができます ここ
このコードを使用します:
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
}
}