web-dev-qa-db-ja.com

ボレーによる応答処理

プロジェクトでネットワークリクエストの処理にVolleyを使用しています。これがサンプルですJSON私のサーバーが返す

JSONオブジェクトの応答

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

JSON配列応答

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

検証エラーまたはその他のエラーが発生すると、サーバーは次の応答を返します。

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

問題はデータの解析にあります。リクエストが成功すると、onResponseResponseListenerで、dataキーのコンテンツを取得します。一方、私は上記と同じ結果を期待していました。 Volleydataのコンテンツのみを返し、完全な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: "",
             }
         ]
}

onResponseResponseListenerで、次のデータを取得します。

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

エラーが発生すると、サーバーは次の応答を返します。

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

このため、VolleyParseExceptionを期待どおりに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圧縮に問題がありました。私はこの質問を閉じることに投票するつもりです。

8
Nitish

しかし、エラーが発生すると、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
   }
5

エラーが発生した場合、サーバーはhttpステータスコード4xxのエラーjsonを返す必要があります。これが、RestfulAPIを設計する方法です。現在の状況では、APIは常に成功したAPI結果に対応する2xxを返します。 APIが正しいhttp応答コード(この場合は401(無許可)または403(禁止) ここを参照 を送信する場合、ErrorListenerはVolleyによって呼び出されます。 ResponseListenerにエラー応答の解析ロジックを記述する必要はありません。これは、REST API httpステータスコードを理解するための良い resource です。

3
JavaGhost

このような状況を処理する効率的な方法は、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' 
2
Chandru

結果のスクリーンショットを更新:

成功例: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);

お役に立てれば!

2
BNK

コードキーの値は、応答が失敗であるか成功であるかを常に利用できるため、確認できます。以下は小さなスニペットです。

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

注:これを行うためのよりモジュール化された方法は、モデルクラスを作成し、それに値を設定することです。この方法では、すべての値を単一のJavaオブジェクトで取得します。

1
Kaveesh Kanwal

多分あなたはこれを試すことができます:
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を見つけることができます ここ

1
uestcfei

このコードを使用します:

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
    }
}
0
Vivek Sinha