I need to parse a custom object that contains another custom object. I have two custom objects: Page and Widget, the Page object has a HashTable of Widget. I want to parse JSON and create an array of Page with various Widget. My request class is:
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 Map<String, String> params;
public GsonRequest(String url, Class<T> classType, HashMap<String, String> params, Response.Listener<T> listener, Response.ErrorListener errorListener) {
super(Method.POST, url, errorListener);
headers = null;
this.clazz = classType;
this.listener = listener;
this.params = params;
}
#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 Map<String, String> getParams() throws AuthFailureError {
return params;
}
#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));
}
}
GsonRequest<Page[]> req = new GsonRequest<Page[]>(url, V10Page[].class, params, new Response.Listener<Page[]>() {
#Override
public void onResponse(Page[] response) {
List<Page> lista = Arrays.asList(response);
//callback.onSuccess(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
System.out.println("Error:" + error.getLocalizedMessage());
}
});
}
The problem is that all the obejcts are null, where is the mistake?
Related
I sent request with postman its working, but volley doesn't work. I always get error! I searched stackoverflow volley returns error when response is empty but i added CustomJsonObjectRequest still the issue remains.
Error message
Volley org.json.JSONException: End of input at character 0 of
CustomJsonObjectRequest
public class CustomJsonObjectRequest extends JsonObjectRequest {
public CustomJsonObjectRequest(int method, String url, JSONObject jsonRequest, Response.Listener<JSONObject> listener, Response.ErrorListener errorListener) {
super(method, url, jsonRequest, listener, errorListener);
}
#Override
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
try {
if (response.data.length == 0) {
byte[] responseData = "{}".getBytes("UTF8");
response = new NetworkResponse(response.statusCode, responseData, response.headers, response.notModified);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return super.parseNetworkResponse(response);
}
}
Volley request
EcoElement ecoElement = ecoElementArrayList.get(position);
Map<String, String> params = new HashMap<String, String>();
params.put("Id", ecoElement.getId().toString());
params.put("Checked", ecoElement.getChecked().toString());
JSONObject ObjParams = new JSONObject(params);
try {
CustomJsonObjectRequest getRequest = new CustomJsonObjectRequest(Request.Method.PUT, "https://ourwebsite.sslbeta.de/api/gardenapi/updateecoelements", ObjParams,
response -> {
Toast.makeText(getContext(), ""+response, Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
},
error -> {
Toast.makeText(getContext(), ""+error.toString(), Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
}
);
RequestQueueSingleton.getInstance(getContext()).addToRequestQueue(getRequest);
} catch (Exception e) {
Toast.makeText(getContext(), e.toString(), Toast.LENGTH_LONG).show();
}
Finally i was able to fix the issues after hours of searching. There were two reasons to this, first is that api was returning null/empty so CustomJsonObjectRequest fixed that, and then another issue is that i forgot to add authentication headers. that was a silly mistake i know!
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Content-Type", "application/json");
headers.put("Authorization", "Bearer "+access_token);
return headers;
}
};
Here is the solution, just create this method and pass your value.
private void CustomJsonObjectRequest() {
String tag_string_req = "req__details";
StringRequest strReq = new StringRequest(Request.Method.POST, <API URL>, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
getPerspective().showErrorLogs(TAG, "Response Invest : " + response);
try {
// Parse your response here
} catch (Exception e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}) {
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("Id", <ID VALUE HERE>);
params.put("Checked", <TRUE or FALSE>);
return params;
}
};
strReq.setRetryPolicy(new RetryPolicy() {
#Override
public void retry(VolleyError arg0) throws VolleyError {
}
#Override
public int getCurrentTimeout() {
return 0;
}
#Override
public int getCurrentRetryCount() {
return 0;
}
});
strReq.setShouldCache(false);
addToRequestQueue(strReq, tag_string_req);
}
Both ID and Checked must have String type.And create below methods in MainActivity:
private RequestQueue mRequestQueue;
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
return mRequestQueue;
}
public <T> void addToRequestQueue(Request<T> req, String tag) {
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
getRequestQueue().add(req);
}
public <T> void addToRequestQueue(Request<T> req) {
req.setTag(TAG);
getRequestQueue().add(req);
}
We have this method to make a request using the Volley library:
public void requestWithSomeHttpHeaders() {
RequestQueue queue = Volley.newRequestQueue(this);
String url = "http://www.somewebsite.com";
StringRequest getRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>()
{
#Override
public void onResponse(String response) {
// response
Log.d("Response", response);
}
},
new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError error) {
// TODO Auto-generated method stub
Log.d("ERROR","error => "+error.toString());
}
}
) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("User-Agent", "Nintendo Gameboy");
params.put("Accept-Language", "fr");
return params;
}
};
queue.add(getRequest);
}
Notice the part:
{
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("User-Agent", "Nintendo Gameboy");
params.put("Accept-Language", "fr");
return params;
}
};
It confuses me because there's no comma before it, so it's not a function argument. If you look at the method definition:
public StringRequest(
int method,
String url,
Listener<String> listener,
#Nullable ErrorListener errorListener) {
super(method, url, errorListener);
mListener = listener;
}
there's no clear code which explains support for this.
What's this concept called and how do you write code that supports this?
This snippet shows the creation of an instance of an anonymous class that extends StringRequest and overrides the getHeaders() method.
Is it possible to change the value of global variable or to return value from volley method. Im trying to return value but im not getting any value from this method. I need to return 'listaFilmovaSerija' ArrayList.
public static ArrayList<MoviesShowsModel> readJSON(Context context, String url, final ArrayList<MoviesShowsModel> listaFilmovaSerija, final boolean odredjenaVelicina){
requestQueue = Volley.newRequestQueue(context);
listaFilmovaSerija.clear();
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET,
url, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
String naslov = "";
JSONObject obj = new JSONObject(response.toString());
JSONArray arr = obj.getJSONArray("results");
int d = (odredjenaVelicina)? 10 : arr.length();
for (int i = 0; i < d; i++){
JSONObject obj2 = arr.getJSONObject(i);
naslov = (getTabActive() == 0)? obj2.getString("title") : obj2.getString("name");
listaFilmovaSerija.add(new MoviesShowsModel(naslov,
obj2.getString("poster_path"),
obj2.getString("overview"),
obj2.getString("backdrop_path"),
obj2.getInt("id")));
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.i("ISPIS","Desila se greska " + error);
}
});
requestQueue.add(jsonObjectRequest);
return listaFilmovaSerija;}
To get the response in ArrayList you have to implement Custom request of type ArrayList then only you will be able to get the desired response.
You can read about it in official documentation
and you can find tutorial here
Example from Official documentation which is Custom GsonRequest
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 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 headers Map of request headers
*/
public GsonRequest(String url, Class<T> clazz, Map<String, String> headers,
Listener<T> listener, ErrorListener errorListener) {
super(Method.GET, url, errorListener);
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
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 wan't send post from JsonArrayRequest to server and I found some answer and I trying it..
but I got error like this
this is my code
HashMap<String, String> params = new HashMap<String, String>();
public void JSON_DATA_WEB_CALL() {
jsonArrayRequest = new JsonArrayRequest(GET_JSON_DATA_HTTP_URL, new JSONObject(params),
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
JSON_PARSE_DATA_AFTER_WEBCALL(response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}){
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("CUSTOM_HEADER", "Yahoo");
headers.put("ANOTHER_CUSTOM_HEADER", "Google");
return headers;
}
};
requestQueue = Volley.newRequestQueue(this);
requestQueue.add(jsonArrayRequest);
}
how to fix that?
Use this custom class.
public class CustomJsonArrayRequest extends JsonRequest<JSONArray> {
/**
* 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 CustomJsonArrayRequest(int method, String url, JSONObject jsonRequest,
Response.Listener<JSONArray> listener, Response.ErrorListener errorListener) {
super(method, url, (jsonRequest == null) ? null : jsonRequest.toString(), listener,
errorListener);
}
#Override
protected Response<JSONArray> parseNetworkResponse(NetworkResponse response) {
try {
String jsonString = new String(response.data,
HttpHeaderParser.parseCharset(response.headers, PROTOCOL_CHARSET));
return Response.success(new JSONArray(jsonString),
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JSONException je) {
return Response.error(new ParseError(je));
}
}
}
Implementation in your case should be something like this:
HashMap<String, String> params = new HashMap<String, String>();
public void JSON_DATA_WEB_CALL() {
CustomJsonArrayRequest request = new CustomJsonArrayRequest (Request.Method.POST, GET_JSON_DATA_HTTP_URL, new JSONObject(params),
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
JSON_PARSE_DATA_AFTER_WEBCALL(response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}){
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("CUSTOM_HEADER", "Yahoo");
headers.put("ANOTHER_CUSTOM_HEADER", "Google");
return headers;
}
};
requestQueue = Volley.newRequestQueue(this);
requestQueue.add(request);
}
I'm trying to send a POST request with paramteres to server. But the post params are always null.
I've tried few solutions from stackoverflow but it didn't work.
I get Unexpected response code 401 for 11.urlname
Map<String, String> jsonParams = new HashMap<String, String>();
jsonParams.put("username", "test#mail.com");
jsonParams.put("usertype", "userType");
jsonParams.put("apikey", "key");
JsonObjectRequest myRequest = new JsonObjectRequest(Request.Method.POST,apiURL, new JSONObject(jsonParams),
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
String status=response.getString("status");
if (status.equals("success"))
{
txtResponse.setText("Valid user");
}
else {
txtResponse.setText("InValid USer");
}
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Content-Type", "application/json; charset=UTF-8");
return headers;
}
};
AppController.getInstance().addToRequestQueue(myRequest, "tag");
My App controller code is
public class AppController extends Application {
public static final String TAG = AppController.class.getSimpleName();
private RequestQueue mRequestQueue;
private static AppController mInstance;
#Override
public void onCreate() {
super.onCreate();
mInstance = this;
}
public static synchronized AppController getInstance() {
return mInstance;
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
return mRequestQueue;
}
public <T> void addToRequestQueue(Request<T> req, String tag) {
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
getRequestQueue().add(req);
}
public <T> void addToRequestQueue(Request<T> req) {
req.setTag(TAG);
getRequestQueue().add(req);
}
public void cancelPendingRequests(Object tag) {
if (mRequestQueue != null) {
mRequestQueue.cancelAll(tag);
}
}
}
If your issue has not been solved, you can refer to the following code to build your request body (params)
private String buildRequestBody(Object content) {
String output = null;
if ((content instanceof String) ||
(content instanceof JSONObject) ||
(content instanceof JSONArray)) {
output = content.toString();
} else if (content instanceof Map) {
Uri.Builder builder = new Uri.Builder();
HashMap hashMap = (HashMap) content;
if (isValid(hashMap)) {
Iterator entries = hashMap.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry entry = (Map.Entry) entries.next();
builder.appendQueryParameter(entry.getKey().toString(), entry.getValue().toString());
entries.remove(); // avoids a ConcurrentModificationException
}
output = builder.build().getEncodedQuery();
}
}
return output;
}
Then...
Map<String, String> stringMap = new HashMap<>();
stringMap.put("username", "yourusername");
stringMap.put("password", "yourpassword");
...
String requestBody = buildRequestBody(stringMap);