Android volley implementing custom request with getParams that accepts JSONArray param - android

I am using Google's Volley to make GET and POST requests using the following custom request class:
public class GsonRequest<T> extends Request<T> {
private static final int SOCKET_TIMEOUT_MS = 30000;
private static final int MAX_RETRIES = 3;
private final Gson gson = new Gson();
private final Type type;
private final Map<String, String> params;
private final Response.Listener<T> listener;
/**
* Make a GET request and return a parsed object from JSON.
*
* #param url URL of the request to make
* #param type Relevant type object, for Gson's reflection
* #param params Map of request params
*/
public GsonRequest(int method, String url, Type type, Map<String, String> params,
Response.Listener<T> listener, Response.ErrorListener errorListener) {
super(method, url, errorListener);
this.type = type;
this.params = params;
this.listener = listener;
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
return headers;
}
#Override
protected Map<String, String> getParams() throws AuthFailureError {
// Here is my question, can I add a param value as JSONArray? like this:
params.put("orderValue", "35");
params.put("price", ""price": ["13.00", "22.00"]");
return params != null ? params : super.getParams();
}
#Override
public Request<?> setRetryPolicy(RetryPolicy retryPolicy) {
final RetryPolicy policy = new DefaultRetryPolicy(SOCKET_TIMEOUT_MS, MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
return super.setRetryPolicy(policy);
}
#Override
public String getBodyContentType() {
return "application/json";
}
#Override
public byte[] getBody() throws AuthFailureError {
try {
Log.i("" + gson.toJson(params).getBytes("utf-8"));
return gson.toJson(params).getBytes("utf-8");
} catch (UnsupportedEncodingException uee) {
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", gson.toJson(params), "utf-8");
return super.getBody();
}
}
#Override
protected void deliverResponse(T response) {
listener.onResponse(response);
}
#Override
protected Response<T> parseNetworkResponse(NetworkResponse response) {
try {
final String json = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
return (Response<T>) Response.success(gson.fromJson(json, type), HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JsonSyntaxException e) {
return Response.error(new ParseError(e));
}
}
}
The Json I'm trying to send:
{
"orderValue": "35",
"price": [
"13.00",
"22.00"
]
}
What is really sent as I get from getBody() method log is:
{
"price": "[\"23.00\",\"55.00\"]",
"orderValue": "35"
}
Any help with this issue?

You need change extends Request to ** JsonObjectRequest** or create JSONArrayRequest object.
public class VolleyJSONObjectRequest extends JsonObjectRequest {
private Context context;
private int timeOut = 10000;
private int maxRetries = 1;
public VolleyJSONObjectRequest(int method, Context context, String url, JSONObject jsonObject, Listener<JSONObject> listener, ErrorListener errorListener) {
super(method, url, jsonObject, listener, errorListener);
super.setRetryPolicy(new DefaultRetryPolicy(timeOut, maxRetries, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
}
public void startRequest() {
VolleyHandler.get(context).addToRequestQueue(this);
}
}
Example method:
private void saveItems(){
if (itens != null && itens.size() > 0) {
try {
JSONArray itensJson = new JSONArray();
for (SalesOrderItem item : itens) { // your loop
JSONObject jsonObject = new JSONObject();
jsonObject.put("price", this.priceOne);
jsonObject.put("price", this.priceTwo);
itensJson.put(jsonObject);
}
JSONObject headerJSON = new JSONObject();
headerJSON.put("price", itensJson);
VolleyJSONObjectRequest request = new VolleyJSONObjectRequest(Request.Method.POST, context, context.getString(R.string.URL_SALES_ORDER_ITENS_INSERT), headerJSON, onResponseItem, onErrorResponseItem);
request.startRequest();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
request = new VolleyStringRequest(context, context.getString(R.string.URL_FINISH_SALES_ORDER_DRAFT), onResponseFinishSalesOrderDraft, onErrorResponseFinishSalesOrderDraft);
request.startRequest();

Related

Custom Gson request and response in post method

What have I done wrong?. How can i resolve this?. Please explain why this error occur. if it is run successfully what is my response?
MainActivity :
public class MainActivity extends AppCompatActivity {
String url = "http://vsstechnology.com/DTSignUp/api/business/create_business.php";
String TAG = "MainActivity";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
HashMap<String, String> params = new HashMap<>();
params.put("address", "xxx");
params.put("business_description", "xx");
params.put("businessEmail", "xxx#gmail.com");
params.put("business_name", "xxx");
params.put("phone", "1234567890");
params.put("business_type", "xx");
params.put("created_by", "xxx");
params.put("customer_name", "xxx");
params.put("email", "yyy#gmail.com");
params.put("firstName", "yyy");
params.put("lastName", "yyy");
params.put("phone", "6544324569");
GsonRequest<Model> gsonRequest = new GsonRequest<Model>(Request.Method.POST, url, Model.class, params, new Response.Listener<Model>() {
#Override
public void onResponse(Model response) {
Toast.makeText(getApplicationContext(), "success" + " " + response, Toast.LENGTH_LONG).show();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getApplicationContext(), "error" + " " + error, Toast.LENGTH_LONG).show();
}
});
requestQueue.add(gsonRequest);
}
}
Model :
public class Model {
private Business business;
private Contacts[] contacts;
private ServerResponse serverResponse;
public Model(Business business, Contacts[] contacts, ServerResponse serverResponse) {
this.business = business;
this.contacts = contacts;
this.serverResponse = serverResponse;
}
public Business getBusiness() {
return business;
}
public void setBusiness(Business business) {
this.business = business;
}
public Contacts[] getContacts() {
return contacts;
}
public void setContacts(Contacts[] contacts) {
this.contacts = contacts;
}
public ServerResponse getServerResponse() {
return serverResponse;
}
public void setServerResponse(ServerResponse serverResponse) {
this.serverResponse = serverResponse;
}
}
custom GsonRequest :
public class GsonRequest<T> extends Request<T> {
private Gson gson = new Gson();
private Class<T> clazz;
private Map<String, String> headers;
private Map<String, String> params;
private Response.Listener<T> listener;
/**
* Make a GET request and return a parsed object from JSON.
*
* #param url URL of the request to make
* #param clazz Relevant class object, for Gson's reflection
* #param params Map of request headers
*/
public GsonRequest(int method, String url, Class<T> clazz, Map<String, String> params,
Response.Listener<T> listener, Response.ErrorListener errorListener) {
super(method, url, errorListener);
this.clazz = clazz;
this.headers = null;
this.params = params;
this.listener = listener;
gson = new Gson();
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
return headers != null ? headers : super.getHeaders();
}
#Override
protected Map<String, String> getParams() throws AuthFailureError {
return super.getParams();
}
#Override
protected void deliverResponse(T response) {
listener.onResponse(response);
}
#Override
protected Response<T> parseNetworkResponse(NetworkResponse response) {
try {
String json = new String(response.data,
HttpHeaderParser.parseCharset(response.headers));
return Response.success(
gson.fromJson(json, clazz),
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JsonSyntaxException e) {
return Response.error(new ParseError(e));
}
}
}
Error :
com.android.volley.ParseError : com.Google.gson.JsonSyntaxException:
java.lang.illegalStateException: Expected BEGIN_OBJECT but was STRING
at line 1 column 1 path $
Based on your error some thing is wrong with your API, to debug it you can use Postman.

how to make post call with custom object using volley in android

am new to android can any one answer for this question please, i tried alot but didn't find correct stuff.i want to send a my custom user object to spring rest service
Employee Object:
in android and spring
public class Employee{
String firstname;
String lastname;
//setters and getter goes here
}
GsonRequest:
public class GsonRequest<T> extends Request<T> {
public final Gson gson = new Gson();
private final Class<T> clazz;
private final Map<String, String> headers;
private final Response.Listener<T> listener;
private final Object dataIn;
/**
* Make a GET request and return a parsed object from JSON.
*
* #param url URL of the request to make
* #param clazz Relevant class object, for Gson's reflection
* #param headers Map of request headers
*/
public GsonRequest(String url, Class<T> clazz, Map<String, String> headers,
Response.Listener<T> listener, Response.ErrorListener errorListener) {
super(Method.GET, url, errorListener);
this.clazz = clazz;
this.headers = headers;
this.listener = listener;
this.dataIn = null;
}
public GsonRequest(String url, Object dataIn, Class<T> clazz, Map<String, String> headers,
Response.Listener<T> listener, Response.ErrorListener errorListener) {
super(Method.POST, url, errorListener);
this.dataIn = dataIn;
this.clazz = clazz;
this.headers = headers;
this.listener = listener;
}
#Override
public byte[] getBody() throws AuthFailureError {
return gson.toJson(dataIn).getBytes();
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
return headers != null ? headers : super.getHeaders();
}
#Override
protected void deliverResponse(T response) {
listener.onResponse(response);
}
#Override
protected Response<T> parseNetworkResponse(NetworkResponse response) {
try {
String json = new String(
response.data,
HttpHeaderParser.parseCharset(response.headers));
return Response.success(
gson.fromJson(json, clazz),
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
}
}
}
Main Activity:
public class MainActivity extends AppCompatActivity {
Button clickbtn;
TextView resText;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
clickbtn=(Button)findViewById(R.id.mybutton);
resText=(TextView)findViewById(R.id.mytext);
clickbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Employee emp=new Employee();
emp.setFirstname("naresh");
RequestQueue queue = Volley.newRequestQueue(getApplicationContext());
GsonRequest<Employee> myReq = new GsonRequest<Employee>("http://192.168.10.37:8088/adduser",
emp,
Employee.class,
new HashMap<String, String>(),
new Response.Listener<Employee>() {
#Override
public void onResponse(Employee response) {
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getApplicationContext(),"error", Toast.LENGTH_SHORT).show();
Log.i("post error","post error",error);
resText.setText(error.getMessage());
Log.d("post error","post error",error);
}
});
queue.add(myReq);
}
});
}
}
spring rest service:
#RequestMapping("adduser")
public void addUser(#Requestbody User user){
Sysetm.out.println(user.getFirstname());
}
Exception:
at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:112)
E/Volley: [216] BasicNetwork.performRequest: Unexpected response code 415 for http://192.168.10.37:8088/adduser
I/post error: post error
com.android.volley.ServerError
at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:163)
at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:112)
D/post error: post error
com.android.volley.ServerError
at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:163)
at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:112)
As my comment, please add headers.put("Content-Type", "application/json; charset=utf-8"); inside getHeaders().

ANDROID Volley + Gson (POST)

hello.
I want to make a post request using gson.
I got the class implemented into android website...
http://developer.android.com/intl/pt-br/training/volley/request-custom.html
UserRequestHelper.userRequest(Request.Method.POST, EndpointURL.USUARIO, null, new Response.Listener<Usuario>() {
#Override
public void onResponse(Usuario response) {
Toast.makeText(getActivity(), "Cadastro realizado com sucesso!", Toast.LENGTH_SHORT).show();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getActivity(), "Erro ao realizar cadastro.", Toast.LENGTH_SHORT).show();
}
});
I need a body to send the user? How i send the object user to make a post request?
Could someone help me with this?
you have to override getBody :
#Override
public byte[] getBody() throws AuthFailureError {
return gson.toJson(dataIn).getBytes();
}
the whole example class(form the same link) edited:
public class GsonRequest<T> extends Request<T> {
private final Gson gson = new Gson();
private final Class<T> clazz;
private final Map<String, String> headers;
private final Response.Listener<T> listener;
private final Object dataIn;
/**
* Make a GET request and return a parsed object from JSON.
*
* #param url URL of the request to make
* #param clazz Relevant class object, for Gson's reflection
* #param headers Map of request headers
*/
public GsonRequest(String url, Object dataIn, Class<T> clazz, Map<String, String> headers,
Response.Listener<T> listener, Response.ErrorListener errorListener) {
super(Method.POST, url, errorListener);
this.dataIn = dataIn;
this.clazz = clazz;
this.headers = headers;
this.listener = listener;
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
return headers != null ? headers : super.getHeaders();
}
#Override
protected void deliverResponse(T response) {
listener.onResponse(response);
}
#Override
public byte[] getBody() throws AuthFailureError {
return gson.toJson(dataIn).getBytes();
}
#Override
protected Response<T> parseNetworkResponse(NetworkResponse response) {
try {
String json = new String(
response.data,
HttpHeaderParser.parseCharset(response.headers));
return Response.success(
gson.fromJson(json, clazz),
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JsonSyntaxException e) {
return Response.error(new ParseError(e));
}
}
}

Android Volley not passing post parameters using custom request

I am using volley for simple REST request and passing some post parameters in it. But It always giving response BasicNetwork.performRequest: Unexpected response code 400.
I have tried following custom request.
public class GsonRequestRest<T> extends Request<T>{
private static final String PROTOCOL_CHARSET = "utf-8";
private static final String PROTOCOL_CONTENT_TYPE = String.format("application/json; charset=%s", PROTOCOL_CHARSET);
private final Listener<T> mListener;
private final String mRequestBody;
private Gson mGson;
private Class<T> mJavaClass;
private Map<String, String> params;
public GsonRequestLoginRest(int method, String url, Class<T> cls, String requestBody, Map<String, String> params,Listener<T> listener,ErrorListener errorListener) {
super(method, url, errorListener);
mGson = new Gson();
mJavaClass = cls;
mListener = listener;
mRequestBody = requestBody;
this.params = params;
}
#Override
protected Map<String, String> getParams() throws com.android.volley.AuthFailureError {
return params;
};
#Override
protected void deliverResponse(T response) {
mListener.onResponse(response);
}
private Map<String, String> headers = new HashMap<String, String>();
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
return headers;
}
#Override
protected Response<T> parseNetworkResponse(NetworkResponse response) {
try {
String jsonString = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
T parsedGSON = mGson.fromJson(jsonString, mJavaClass);
return Response.success(parsedGSON,HttpHeaderParser.parseCacheHeaders(response));
} catch (IOException e) {
Log.d("tag", e.getMessage());
return Response.error(new ParseError(e));
} catch (JsonSyntaxException je) {
return Response.error(new ParseError(je));
}
}
#Override
public String getBodyContentType() {
return PROTOCOL_CONTENT_TYPE;
}
#Override
public byte[] getBody() {
try {
return mRequestBody == null ? null : mRequestBody.getBytes(PROTOCOL_CHARSET);
} catch (UnsupportedEncodingException uee) {
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s",mRequestBody, PROTOCOL_CHARSET);
return null;
}
}
//In your extended request class
#Override
protected VolleyError parseNetworkError(VolleyError volleyError){
if(volleyError.networkResponse != null && volleyError.networkResponse.data != null){
VolleyError error = new VolleyError(new String(volleyError.networkResponse.data));
volleyError = error;
}
return volleyError;
}
}
I did try to override getParams() and pass parameters in it. But it was not passing parameters and throwing error 400. I tried many of suggestions here and here but nothing worked for me. Is there any bug in Volley. ?
Please guide.
it working for me when use getBody() instead of getParams() in Request class.
another thing you should use JSONObject instead of HashMap
to put your params
.
then convert the JSONObject to string and convert string to byte in the getBody method.
use this link for more explanation.
How to send a POST request using volley with string body?
Hope my answer clarified enough to you.

Creating a Jackson parsed request in Volley

I want to create a JacksonJSONRequest implementation in Volley. My requests/responses like most will have a request object of type X, and a response object of type Y.
The Volley Request base class defines both as the same...
public class JacksonRequest<T> extends Request<T>
...
protected Response<T> parseNetworkResponse(NetworkResponse response)
This doesn't make much sense to me. I can't imagine many REST requests using the same structure for request and responses.
Am I missing something obvious here?
Here is my implementation...
public class JacksonRequest<T> extends JsonRequest<T>
{
private Class<T> responseType;
/**
* Creates a new request.
*
* #param method
* the HTTP method to use
* #param url
* URL to fetch the JSON from
* #param requestData
* A {#link Object} to post and convert into json as 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 JacksonRequest(int method, String url, Object requestData, Class<T> responseType, Listener<T> listener, ErrorListener errorListener)
{
super(method, url, (requestData == null) ? null : Mapper.string(requestData), listener, errorListener);
this.responseType = responseType;
}
#Override
protected Response<T> parseNetworkResponse(NetworkResponse response)
{
try
{
String jsonString = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
return Response.success(Mapper.objectOrThrow(jsonString, responseType), HttpHeaderParser.parseCacheHeaders(response));
}
catch (Exception e)
{
return Response.error(new ParseError(e));
}
}
}
The Mapper class which the above uses is just a small wrapper class...
/**
* Singleton wrapper class which configures the Jackson JSON parser.
*/
public final class Mapper
{
private static ObjectMapper MAPPER;
public static ObjectMapper get()
{
if (MAPPER == null)
{
MAPPER = new ObjectMapper();
// This is useful for me in case I add new object properties on the server side which are not yet available on the client.
MAPPER.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
return MAPPER;
}
public static String string(Object data)
{
try
{
return get().writeValueAsString(data);
}
catch (Exception e)
{
e.printStackTrace();
return null;
}
}
public static <T> T objectOrThrow(String data, Class<T> type) throws JsonParseException, JsonMappingException, IOException
{
return get().readValue(data, type);
}
public static <T> T object(String data, Class<T> type)
{
try
{
return objectOrThrow(data, type);
}
catch (Exception e)
{
e.printStackTrace();
return null;
}
}
}
Not sure this is going to help you, but I have a jackson request that take a type and return a string, I use it because most of my requests just return a header
Edit
This have different request and response types, it's not super elegant but it works
public class JacksonJsonRequest<K, T> extends Request<T> {
private ObjectMapper mMapper = new ObjectMapper();
private static final String PROTOCOL_CHARSET = "utf-8";
private static final String PROTOCOL_CONTENT_TYPE =
String.format("application/json; charset=%s", PROTOCOL_CHARSET);
private final Response.Listener<T> mListener;
private final K mRequestBody;
private final Class<T> mClass;
private final Map<String, String> mHeaders;
public JacksonJsonRequest(int method, String url, K requestBody,
Response.ErrorListener errorListener, Response.Listener<T> listener,
Map<String, String> headers, Class<T> claz) {
super(method, url, errorListener);
mListener = listener;
mRequestBody = requestBody;
mHeaders = headers;
mClass = claz;
}
#Override
protected Response<T> parseNetworkResponse(NetworkResponse networkResponse) {
String jsonString = new String(networkResponse.data);
try {
T result = mMapper.readValue(jsonString, mClass);
return Response.success(result, HttpHeaderParser.parseCacheHeaders(networkResponse));
} catch (IOException e) {
Log.e("jacksontest", "error parsing", e);
}
return null;
}
#Override
protected void deliverResponse(T t) {
mListener.onResponse(t);
}
#Override
public String getBodyContentType() {
return PROTOCOL_CONTENT_TYPE;
}
#Override
public byte[] getBody() {
try {
return mRequestBody == null ? null : mMapper.writeValueAsBytes(mRequestBody);
} catch (JsonProcessingException e) {
Log.e("Jacksontest", "error parsing", e);
}
return null;
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
return (mHeaders == null) ? super.getHeaders() : mHeaders;
}
}

Categories

Resources