【问题标题】:Send POST request with JSON data using Volley使用 Volley 发送带有 JSON 数据的 POST 请求
【发布时间】:2014-06-06 21:25:52
【问题描述】:

我想发送一个新的JsonObjectRequest 请求:

  • 我想接收 JSON 数据(来自服务器的响应):OK
  • 我想通过这个请求向服务器发送 JSON 格式的数据

    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;
            }
        };
    

附:我也在我的项目中使用 GSON 库。

【问题讨论】:

    标签: android http-post android-volley android-json


    【解决方案1】:

    JsonObjectRequest 实际上接受 JSONObject 作为正文。

    来自this blog article

    final String url = "some/url";
    final JSONObject jsonBody = new JSONObject("{\"type\":\"example\"}");
    
    new JsonObjectRequest(url, jsonBody, new Response.Listener<JSONObject>() { ... });
    

    这里是source code and 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);
    }
    

    【讨论】:

    • HashMap 在您的示例中有点多余。您可以将“令牌”直接放入JSONObject,而无需中间映射。
    • @shkschneider 我在 jsonBody 上遇到类型不兼容的错误。是否需要将 String 转换为 JSONObject ?
    • @KarthikeyanVe 你是对的,改用new JSONObject("{\"type\":\"example\"}")——我的错。
    【解决方案2】:

    我知道这个帖子已经很老了,但是我遇到了这个问题,我想出了一个很酷的解决方案,它对许多人来说非常有用,因为它在许多方面纠正/扩展了 Volley 库。

    我发现了一些不受支持的开箱即用 Volley 功能:

    • 这个JSONObjectRequest 并不完美:您必须在结尾处期待JSON(请参阅Response.Listener&lt;JSONObject&gt;)。
    • Empty Responses(只有 200 状态)呢?
    • 如果我想直接从ResponseListener 获取我的 POJO,我该怎么办?

    我或多或少在一个大的泛型类中编译了很多解决方案,以便为我引用的所有问题找到解决方案。

      /**
      * 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
             // ...
         }
     }
    

    这似乎有点矫枉过正,但拥有所有这些构造函数非常酷,因为您拥有所有案例:

    (虽然可以直接使用主构造函数,但它当然是可能的)。

    1. 请求的响应解析为 POJO/标头手动设置/POJO 发送
    2. 响应解析为 POJO/POJO 以发送的请求
    3. 响应解析为 POJO/要发送的字符串的请求
    4. 响应解析为 POJO (GET) 的请求
    5. 响应解析为 POJO (GET) 的请求/手动设置的标头
    6. 请求无响应(200 - 空正文)/手动设置标头/要发送的 POJO
    7. 没有响应的请求(200 - 空正文)/要发送的 POJO
    8. 没有响应的请求(200 - 空正文)/要发送的字符串

    当然,为了让它工作,你必须有谷歌的 GSON Lib;只需添加:

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

    到您的依赖项(当前版本是2.3.1)。

    【讨论】:

    • 好答案,感谢分享。我只需将 toBeSent 参数的类型从 Object 更改为 T 以提高类型安全性。
    • 是的,好主意,随时编辑!这是社区的东西:D(我目前在移动)
    • 我也在尝试做类似的事情,但它比我要创建的要好得多......
    • 好一个适合客户端服务器通信中的所有场景。
    • 很好的答案。如果您为此创建一些教程非常好
    【解决方案3】:
    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);
    

    refer

    【讨论】:

      【解决方案4】:
      • 创建RequestQueue 类的对象。

        RequestQueue queue = Volley.newRequestQueue(this);
        
      • 创建一个带有响应和错误侦听器的StringRequest

         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;
            }
        };
        
      • 将您的请求添加到RequestQueue

        queue.add(jsObjRequest);
        
      • 创建PostCommentResponseListener 界面,以便您可以看到它。这是异步请求的简单委托。

        public interface PostCommentResponseListener {
        public void requestStarted();
        public void requestCompleted();
        public void requestEndedWithError(VolleyError error);
        }
        
      • AndroidManifest.xml 文件中包含 INTERNET 权限。

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

      【讨论】:

      • 不回答问题。 Not 是真正的 json 请求,请求体中没有发送数据。
      • 这很有帮助。 tnx
      • 这是一个 POST 数据请求,而不是 JSON 请求。否决票。根本不回答问题。
      【解决方案5】:
          final String url = "some/url";
      

      代替:

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

      你可以使用:

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

      【讨论】:

        【解决方案6】:

        您还可以通过覆盖JsonObjectRequest 类的getBody() 方法来发送数据。如下图。

            @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;
            }
        

        【讨论】:

          【解决方案7】:
          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);
          
          }
          

          【讨论】:

          • 这不会在正文中添加参数作为 JSON 数据
          【解决方案8】:
          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;
          }
          

          【讨论】:

          • 请澄清您的问题
          • @AlexFilatov 哪个问题?
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-09-18
          • 2013-08-05
          • 2014-12-06
          • 1970-01-01
          相关资源
          最近更新 更多