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