Gửi yêu cầu ĐĂNG với dữ liệu JSON bằng Volley


84

Tôi muốn gửi một JsonObjectRequestyêu cầu mới :

  • Tôi muốn nhận dữ liệu JSON (phản hồi từ máy chủ): OK
  • Tôi muốn gửi dữ liệu có định dạng JSON với yêu cầu này đến máy chủ

    JsonObjectRequest request = new JsonObjectRequest(
        Request.Method.POST, "myurl.com", null,
        new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {
                //...
            }
        },
        new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                //...
            }
        })
        {
            @Override
            protected Map<String,String> getParams() {
                // something to do here ??
                return params;
            }
    
            @Override
            public Map<String, String> getHeaders() throws AuthFailureError {
                // something to do here ??
                return params;
            }
        };
    

Tái bút Tôi cũng sử dụng thư viện GSON trong dự án của mình.

Câu trả lời:


88

JsonObjectRequestthực sự chấp nhận JSONObjectnhư một cơ thể.

Từ bài viết blog này ,

final String url = "some/url";
final JSONObject jsonBody = new JSONObject("{\"type\":\"example\"}");

new JsonObjectRequest(url, jsonBody, new Response.Listener<JSONObject>() { ... });

Đây là mã nguồn và JavaDoc ( @param jsonRequest):

/**
 * Creates a new request.
 * @param method the HTTP method to use
 * @param url URL to fetch the JSON from
 * @param jsonRequest A {@link JSONObject} to post with the request. Null is allowed and
 *   indicates no parameters will be posted along with request.
 * @param listener Listener to receive the JSON response
 * @param errorListener Error listener, or null to ignore errors.
 */
public JsonObjectRequest(int method, String url, JSONObject jsonRequest,
        Listener<JSONObject> listener, ErrorListener errorListener) {
    super(method, url, (jsonRequest == null) ? null : jsonRequest.toString(), listener,
                errorListener);
}

1
Đây HashMaplà loại thừa trong ví dụ của bạn. Bạn có thể đặt trực tiếp 'mã thông báo' vào a JSONObjectmà không cần bản đồ trung gian.
Itai Hanski

@shkschneider Tôi đang gặp lỗi loại không tương thích trên jsonBody. Có cần chuyển đổi Chuỗi thành JSONObject không?
Karthikeyan Ve

1
@KarthikeyanVe bạn nói đúng, hãy sử dụng new JSONObject("{\"type\":\"example\"}")thay thế - tệ của tôi.
shkschneider

43

Tôi biết rằng chủ đề này khá cũ, nhưng tôi đã gặp vấn đề này và tôi đã đưa ra một giải pháp tuyệt vời có thể rất hữu ích cho nhiều người vì nó sửa / mở rộng thư viện Volley trên nhiều khía cạnh.

Tôi phát hiện một số tính năng Volley không được hỗ trợ:

  • Điều này JSONObjectRequestkhông hoàn hảo: bạn phải mong đợi một JSONở cuối (xem phần Response.Listener<JSONObject>).
  • Còn về Phản hồi trống (chỉ với trạng thái 200) thì sao?
  • Tôi phải làm gì nếu muốn trực tiếp POJO của mình từ ResponseListener?

Ít nhiều tôi đã biên soạn rất nhiều giải pháp trong một lớp học chung chung lớn để có giải pháp cho tất cả các vấn đề mà tôi đã trích dẫn.

  /**
  * Created by laurentmeyer on 25/07/15.
  */
 public class GenericRequest<T> extends JsonRequest<T> {

     private final Gson gson = new Gson();
     private final Class<T> clazz;
     private final Map<String, String> headers;
     // Used for request which do not return anything from the server
     private boolean muteRequest = false;

     /**
      * Basically, this is the constructor which is called by the others.
      * It allows you to send an object of type A to the server and expect a JSON representing a object of type B.
      * The problem with the #JsonObjectRequest is that you expect a JSON at the end.
      * We can do better than that, we can directly receive our POJO.
      * That's what this class does.
      *
      * @param method:        HTTP Method
      * @param classtype:     Classtype to parse the JSON coming from the server
      * @param url:           url to be called
      * @param requestBody:   The body being sent
      * @param listener:      Listener of the request
      * @param errorListener: Error handler of the request
      * @param headers:       Added headers
      */
     private GenericRequest(int method, Class<T> classtype, String url, String requestBody,
                           Response.Listener<T> listener, Response.ErrorListener errorListener, Map<String, String> headers) {
         super(method, url, requestBody, listener,
                 errorListener);
         clazz = classtype;
         this.headers = headers;
         configureRequest();
     }

     /**
      * Method to be called if you want to send some objects to your server via body in JSON of the request (with headers and not muted)
      *
      * @param method:        HTTP Method
      * @param url:           URL to be called
      * @param classtype:     Classtype to parse the JSON returned from the server
      * @param toBeSent:      Object which will be transformed in JSON via Gson and sent to the server
      * @param listener:      Listener of the request
      * @param errorListener: Error handler of the request
      * @param headers:       Added headers
      */
     public GenericRequest(int method, String url, Class<T> classtype, Object toBeSent,
                           Response.Listener<T> listener, Response.ErrorListener errorListener, Map<String, String> headers) {
         this(method, classtype, url, new Gson().toJson(toBeSent), listener,
                 errorListener, headers);
     }

     /**
      * Method to be called if you want to send some objects to your server via body in JSON of the request (without header and not muted)
      *
      * @param method:        HTTP Method
      * @param url:           URL to be called
      * @param classtype:     Classtype to parse the JSON returned from the server
      * @param toBeSent:      Object which will be transformed in JSON via Gson and sent to the server
      * @param listener:      Listener of the request
      * @param errorListener: Error handler of the request
      */
     public GenericRequest(int method, String url, Class<T> classtype, Object toBeSent,
                           Response.Listener<T> listener, Response.ErrorListener errorListener) {
         this(method, classtype, url, new Gson().toJson(toBeSent), listener,
                 errorListener, new HashMap<String, String>());
     }

     /**
      * Method to be called if you want to send something to the server but not with a JSON, just with a defined String (without header and not muted)
      *
      * @param method:        HTTP Method
      * @param url:           URL to be called
      * @param classtype:     Classtype to parse the JSON returned from the server
      * @param requestBody:   String to be sent to the server
      * @param listener:      Listener of the request
      * @param errorListener: Error handler of the request
      */
     public GenericRequest(int method, String url, Class<T> classtype, String requestBody,
                           Response.Listener<T> listener, Response.ErrorListener errorListener) {
         this(method, classtype, url, requestBody, listener,
                 errorListener, new HashMap<String, String>());
     }

     /**
      * Method to be called if you want to GET something from the server and receive the POJO directly after the call (no JSON). (Without header)
      *
      * @param url:           URL to be called
      * @param classtype:     Classtype to parse the JSON returned from the server
      * @param listener:      Listener of the request
      * @param errorListener: Error handler of the request
      */
     public GenericRequest(String url, Class<T> classtype, Response.Listener<T> listener, Response.ErrorListener errorListener) {
         this(Request.Method.GET, url, classtype, "", listener, errorListener);
     }

     /**
      * Method to be called if you want to GET something from the server and receive the POJO directly after the call (no JSON). (With headers)
      *
      * @param url:           URL to be called
      * @param classtype:     Classtype to parse the JSON returned from the server
      * @param listener:      Listener of the request
      * @param errorListener: Error handler of the request
      * @param headers:       Added headers
      */
     public GenericRequest(String url, Class<T> classtype, Response.Listener<T> listener, Response.ErrorListener errorListener, Map<String, String> headers) {
         this(Request.Method.GET, classtype, url, "", listener, errorListener, headers);
     }

     /**
      * Method to be called if you want to send some objects to your server via body in JSON of the request (with headers and muted)
      *
      * @param method:        HTTP Method
      * @param url:           URL to be called
      * @param classtype:     Classtype to parse the JSON returned from the server
      * @param toBeSent:      Object which will be transformed in JSON via Gson and sent to the server
      * @param listener:      Listener of the request
      * @param errorListener: Error handler of the request
      * @param headers:       Added headers
      * @param mute:          Muted (put it to true, to make sense)
      */
     public GenericRequest(int method, String url, Class<T> classtype, Object toBeSent,
                           Response.Listener<T> listener, Response.ErrorListener errorListener, Map<String, String> headers, boolean mute) {
         this(method, classtype, url, new Gson().toJson(toBeSent), listener,
                 errorListener, headers);
         this.muteRequest = mute;
     }

     /**
      * Method to be called if you want to send some objects to your server via body in JSON of the request (without header and muted)
      *
      * @param method:        HTTP Method
      * @param url:           URL to be called
      * @param classtype:     Classtype to parse the JSON returned from the server
      * @param toBeSent:      Object which will be transformed in JSON via Gson and sent to the server
      * @param listener:      Listener of the request
      * @param errorListener: Error handler of the request
      * @param mute:          Muted (put it to true, to make sense)
      */
     public GenericRequest(int method, String url, Class<T> classtype, Object toBeSent,
                           Response.Listener<T> listener, Response.ErrorListener errorListener, boolean mute) {
         this(method, classtype, url, new Gson().toJson(toBeSent), listener,
                 errorListener, new HashMap<String, String>());
         this.muteRequest = mute;

     }

     /**
      * Method to be called if you want to send something to the server but not with a JSON, just with a defined String (without header and not muted)
      *
      * @param method:        HTTP Method
      * @param url:           URL to be called
      * @param classtype:     Classtype to parse the JSON returned from the server
      * @param requestBody:   String to be sent to the server
      * @param listener:      Listener of the request
      * @param errorListener: Error handler of the request
      * @param mute:          Muted (put it to true, to make sense)
      */
     public GenericRequest(int method, String url, Class<T> classtype, String requestBody,
                           Response.Listener<T> listener, Response.ErrorListener errorListener, boolean mute) {
         this(method, classtype, url, requestBody, listener,
                 errorListener, new HashMap<String, String>());
         this.muteRequest = mute;

     }


     @Override
     protected Response<T> parseNetworkResponse(NetworkResponse response) {
         // The magic of the mute request happens here
         if (muteRequest) {
             if (response.statusCode >= 200 && response.statusCode <= 299) {
                 // If the status is correct, we return a success but with a null object, because the server didn't return anything
                 return Response.success(null, HttpHeaderParser.parseCacheHeaders(response));
             }
         } else {
             try {
                 // If it's not muted; we just need to create our POJO from the returned JSON and handle correctly the errors
                 String json = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
                 T parsedObject = gson.fromJson(json, clazz);
                 return Response.success(parsedObject, HttpHeaderParser.parseCacheHeaders(response));
             } catch (UnsupportedEncodingException e) {
                 return Response.error(new ParseError(e));
             } catch (JsonSyntaxException e) {
                 return Response.error(new ParseError(e));
             }
         }
         return null;
     }

     @Override
     public Map<String, String> getHeaders() throws AuthFailureError {
         return headers != null ? headers : super.getHeaders();
     }

     private void configureRequest() {
         // Set retry policy
         // Add headers, for auth for example
         // ...
     }
 }

Nó có vẻ hơi quá mức cần thiết nhưng thật tuyệt khi có tất cả các hàm tạo này vì bạn có tất cả các trường hợp:

(Hàm tạo chính không được sử dụng trực tiếp mặc dù tất nhiên là có thể).

  1. Yêu cầu với phản hồi được phân tích cú pháp thành POJO / Tiêu đề được đặt theo cách thủ công / POJO thành Gửi
  2. Yêu cầu với phản hồi được phân tích cú pháp thành POJO / POJO để gửi
  3. Yêu cầu với phản hồi được phân tích cú pháp thành POJO / Chuỗi để gửi
  4. Yêu cầu với phản hồi được phân tích cú pháp thành POJO (GET)
  5. Yêu cầu với phản hồi được phân tích cú pháp thành POJO (GET) / Tiêu đề được đặt theo cách thủ công
  6. Yêu cầu không có phản hồi (200 - Phần nội dung trống) / Tiêu đề được đặt theo cách thủ công / POJO để gửi
  7. Yêu cầu không có phản hồi (200 - Nội dung trống) / POJO để gửi
  8. Yêu cầu không có phản hồi (200 - Nội dung trống) / Chuỗi để gửi

Tất nhiên, để nó hoạt động, bạn phải có GSON Lib của Google; chỉ cần thêm:

compile 'com.google.code.gson:gson:x.y.z'

cho các phụ thuộc của bạn (phiên bản hiện tại là 2.3.1).


Câu trả lời tốt, cảm ơn vì đã chia sẻ. Tôi sẽ chỉ thay đổi loại toBeSentthông số từ Objectthành Tđể an toàn hơn cho loại.
Diederik

Vâng, ý kiến ​​hay, hãy chỉnh sửa nó! Đó là thứ cộng đồng nào: D (Tôi đang trên điện thoại di động, hiện tại)
Laurent Meyer

Tôi cũng đang cố gắng để làm điều tương tự nhưng nó là tốt hơn nhiều so tôi đang đi để tạo ra ....
Manish Singla

1
Tốt một phù hợp cho tất cả các kịch bản trong giao tiếp máy chủ khách hàng.
Mukesh

tốt answer.if bạn tạo ra một số hướng dẫn cho điều này rất tốt đẹp của nó
Ali Khaki

29
final String URL = "/volley/resource/12";
// Post params to be sent to the server
HashMap<String, String> params = new HashMap<String, String>();
params.put("token", "AbCdEfGh123456");

JsonObjectRequest req = new JsonObjectRequest(URL, new JSONObject(params),
       new Response.Listener<JSONObject>() {
           @Override
           public void onResponse(JSONObject response) {
               try {
                   VolleyLog.v("Response:%n %s", response.toString(4));
               } catch (JSONException e) {
                   e.printStackTrace();
               }
           }
       }, new Response.ErrorListener() {
           @Override
           public void onErrorResponse(VolleyError error) {
               VolleyLog.e("Error: ", error.getMessage());
           }
       });

// add the request object to the queue to be executed
ApplicationController.getInstance().addToRequestQueue(req);

tham khảo


10
  • Tạo một đối tượng của RequestQueuelớp.

    RequestQueue queue = Volley.newRequestQueue(this);
    
  • Tạo một StringRequestphản hồi và trình nghe lỗi.

     StringRequest sr = new StringRequest(Request.Method.POST,"http://api.someservice.com/post/comment", new Response.Listener<String>() {
        @Override
        public void onResponse(String response) {
            mPostCommentResponse.requestCompleted();
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            mPostCommentResponse.requestEndedWithError(error);
        }
    }){
        @Override
        protected Map<String,String> getParams(){
            Map<String,String> params = new HashMap<String, String>();
            params.put("user",userAccount.getUsername());
            params.put("pass",userAccount.getPassword());
            params.put("comment", Uri.encode(comment));
            params.put("comment_post_ID",String.valueOf(postId));
            params.put("blogId",String.valueOf(blogId));
    
            return params;
        }
    
        @Override
        public Map<String, String> getHeaders() throws AuthFailureError {
            Map<String,String> params = new HashMap<String, String>();
            params.put("Content-Type","application/x-www-form-urlencoded");
            return params;
        }
    };
    
  • Thêm yêu cầu của bạn vào RequestQueue.

    queue.add(jsObjRequest);
    
  • Tạo PostCommentResponseListenergiao diện để bạn có thể nhìn thấy nó. Đó là một đại biểu đơn giản cho yêu cầu không đồng bộ.

    public interface PostCommentResponseListener {
    public void requestStarted();
    public void requestCompleted();
    public void requestEndedWithError(VolleyError error);
    }
    
  • Bao gồm quyền INTERNET bên trong AndroidManifest.xmltệp.

    <uses-permission android:name="android.permission.INTERNET"/>
    

1
Không trả lời câu hỏi. Không phải là một yêu cầu json thực và dữ liệu không được gửi trong phần thân yêu cầu.
Renascienza 19/1214

điều này rất hữu ích. tnx
Diyaa

1
Đây là yêu cầu dữ liệu POST, không phải là yêu cầu JSON. Phản đối. Không trả lời câu hỏi nào cả.
Marc DiMillo

4
    final String url = "some/url";

thay vì:

    final JSONObject jsonBody = "{\"type\":\"example\"}";

bạn có thể dùng:

  JSONObject jsonBody = new JSONObject();
    try {
        jsonBody.put("type", "my type");
    } catch (JSONException e) {
        e.printStackTrace();
    }
new JsonObjectRequest(url, jsonBody, new Response.Listener<JSONObject>() { ... });

1
final Map<String,String> params = new HashMap<String,String>();
        params.put("email", customer.getEmail());
        params.put("password", customer.getPassword());
        String url = Constants.BASE_URL+"login";

doWebRequestPost(url, params);


public void doWebRequestPost(String url, final Map<String,String> json){
        getmDialogListener().showDialog();

    StringRequest post = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
        @Override
        public void onResponse(String response) {
            try {
                getmDialogListener().dismissDialog();
                response....

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            Log.d(App.TAG,error.toString());
            getmDialogListener().dismissDialog();

        }
    }){
        @Override
        protected Map<String, String> getParams() throws AuthFailureError {
            Map<String,String> map = json;

            return map;
        }
    };
    App.getInstance().getRequestQueue().add(post);

}

này không thêm params như dữ liệu JSON trong cơ thể
Haseeb Zulfiqar

1

Bạn cũng có thể gửi dữ liệu bằng getBody()phương pháp ghi đè JsonObjectRequestlớp. Như hình bên dưới.

    @Override
    public byte[] getBody()
    {

        JSONObject jsonObject = new JSONObject();
        String body = null;
        try
        {
            jsonObject.put("username", "user123");
            jsonObject.put("password", "Pass123");

            body = jsonObject.toString();
        } catch (JSONException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        try
        {
            return body.toString().getBytes("utf-8");
        } catch (UnsupportedEncodingException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

0
protected Map<String, String> getParams() {
   Map<String, String> params = new HashMap<String, String>();

   JSONObject JObj = new JSONObject();

   try {
           JObj.put("Id","1");
           JObj.put("Name", "abc");

   } catch (Exception e) {
       e.printStackTrace();
   }

   params.put("params", JObj.toString());
   // Map.Entry<String,String>
   Log.d("Parameter", params.toString());
   return params;
}

1
xin vui lòng làm rõ câu hỏi của bạn
Alex Filatov

1
@AlexFilatov câu hỏi nào?
Thomas Ayoub
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.