使用 Volley 发送带有 JSON 数据的 POST 请求
Posted
技术标签:
【中文标题】使用 Volley 发送带有 JSON 数据的 POST 请求【英文标题】:Send POST request with JSON data using Volley 【发布时间】:2014-06-06 21:25:52 【问题描述】:我想发送一个新的JsonObjectRequest
请求:
我想通过这个请求向服务器发送 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 库。
【问题讨论】:
【参考方案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<JSONObject>
)。
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
// ...
这似乎有点矫枉过正,但拥有所有这些构造函数非常酷,因为您拥有所有案例:
(虽然可以直接使用主构造函数,但它当然是可能的)。
-
请求的响应解析为 POJO/标头手动设置/POJO 发送
响应解析为 POJO/POJO 以发送的请求
响应解析为 POJO/要发送的字符串的请求
响应解析为 POJO (GET) 的请求
响应解析为 POJO (GET) 的请求/手动设置的标头
请求无响应(200 - 空正文)/手动设置标头/要发送的 POJO
没有响应的请求(200 - 空正文)/要发送的 POJO
没有响应的请求(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 哪个问题?以上是关于使用 Volley 发送带有 JSON 数据的 POST 请求的主要内容,如果未能解决你的问题,请参考以下文章
Android Kotlin Volley 如何发送 JSON 数据
带有参数的 Volley jsonObjectRequest 不起作用