volley jsonobjectrequest example android http-post android-volley android-json

android - jsonobjectrequest - Enviar solicitud POST con datos JSON utilizando Volley



android volley post parameters (8)

Me gustaría enviar una nueva solicitud JsonObjectRequest :

  • Deseo recibir datos JSON (respuesta del servidor): OK
  • Deseo enviar datos formateados JSON con esta solicitud al servidor

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

PD. También uso la biblioteca GSON en mi proyecto.


Sé que este hilo es bastante viejo, pero tuve este problema y se me ocurrió una solución genial que puede ser muy útil para muchos porque corrige / amplía la biblioteca de Volley en muchos aspectos.

Descubrí algunas características de Volley no compatibles:

  • Esta JSONObjectRequest no es perfecta: debe esperar un JSON al final (consulte Response.Listener<JSONObject> ).
  • ¿Qué pasa con las respuestas vacías (solo con un estado de 200)?
  • ¿Qué hago si quiero directamente mi POJO del ResponseListener ?

Más o menos compilé muchas soluciones en una gran clase genérica para tener una solución para todo el problema que cité.

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

Puede parecer un poco exagerado, pero es genial tener todos estos constructores porque tienes todos los casos:

(El constructor principal no estaba destinado a ser utilizado directamente aunque, por supuesto, es posible).

  1. Solicitud con respuesta analizada a POJO / Encabezados configurados manualmente / POJO a Enviar
  2. Solicitud con respuesta analizada a POJO / POJO para enviar
  3. Solicitud con respuesta analizada a POJO / String para enviar
  4. Solicitud con respuesta analizada a POJO (GET)
  5. Solicitud con respuesta analizada en POJO (GET) / Encabezados configurados manualmente
  6. Solicitud sin respuesta (200 - Cuerpo vacío) / Encabezados configurados manualmente / POJO para enviar
  7. Solicitud sin respuesta (200 - Empty Body) / POJO to Send
  8. Solicitud sin respuesta (200 - Empty Body) / String to Send

Por supuesto, para que funcione, debe tener GSON Lib de Google; solo agrega:

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

a sus dependencias (la versión actual es 2.3.1 ).


También puede enviar datos sobrescribiendo el método getBody() de la clase JsonObjectRequest . Como se muestra abajo.

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


JsonObjectRequest realmente acepta JSONObject como cuerpo.

De este artículo de blog ,

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

Aquí está el código fuente y 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); }


final String url = "some/url";

en lugar de:

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

puedes usar:

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


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


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

referir


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


  • Crea un objeto de clase RequestQueue .

    RequestQueue queue = Volley.newRequestQueue(this);

  • Cree un StringRequest con respuesta y escucha de error.

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

  • Agregue su solicitud en RequestQueue .

    queue.add(jsObjRequest);

  • Crea la interfaz PostCommentResponseListener solo para que puedas verla. Es un simple delegado para la solicitud asincrónica.

    public interface PostCommentResponseListener { public void requestStarted(); public void requestCompleted(); public void requestEndedWithError(VolleyError error); }

  • Incluye permiso de INTERNET dentro del archivo AndroidManifest.xml .

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