i have an json object like this and i am getting this response in my Fragment.
json
{
"data":{
"categories":[
{
"id":"d5c4eedf-093e-422f-8335-6c6376ca3ccb",
"schedule_m_id":1,
"title_en":"Bakery Products",
"title_fr":"Produits de boulangerie",
"subtitle_en":"Bread, Cakes, Cookies, Crackers, Pies",
"subtitle_fr":"Pain, gateaux, biscuits, craquelins, tartes",
"created_at":"2015-03-04 15:39:44",
"updated_at":"2015-03-04 15:39:44"
},
{
"id":"6d1d4945-9910-40ae-82a8-3fe4137c24c2",
"schedule_m_id":2,
"title_en":"Beverages",
"title_fr":"Boissons",
"subtitle_en":"Soft Drinks, Coffee, Tea, Cocoa",
"subtitle_fr":"Boissons gazeuses, café, thé, cacao",
"created_at":"2015-03-04 15:39:44",
"updated_at":"2015-03-04 15:39:44"
}
]
},
"result":"success"
}
and my categories class is like this:
public class Categories {
private int id;
private String title_en;
private String title_fr;
private int schedule_m_id;
private String subtitle_en;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle_en() {
return title_en;
}
public void setTitle_en(String title_en) {
this.title_en = title_en;
}
public String getTitle_fr() {
return title_fr;
}
public void setTitle_fr(String title_fr) {
this.title_fr = title_fr;
}
public int getSchedule_m_id() {
return schedule_m_id;
}
public void setSchedule_m_id(int schedule_m_id) {
this.schedule_m_id = schedule_m_id;
}
public String getSubtitle_en() {
return subtitle_en;
}
public void setSubtitle_en(String subtitle_en) {
this.subtitle_en = subtitle_en;
}
}
In my fragment how can i parse this json object. i need to make an ArrayList which type is "Categories". i need this Categories object List to make an custom adapter. Can anybode help me.
JSONObject jsonObject = (JSONObject) response;
JSONObject dataProject = jsonObject.getJSONObject("data");
JSONArray products = dataProject.getJSONArray("categories");
Gson gson = new Gson();
Categories categories = new Categories();
ArrayList<Categories> items = new ArrayList<Categories>();
int productCount = products.length();
for (int i = 0; i < productCount; i++) {
categories = gson.fromJson(products.get(i), Categories.class);
items.add(categories);
}
```
I posting a class working with gson volley May be Helpful for you....
Step1. For Parsing your json data use "www.jsonschema2pojo.org/" and generate pojo classes. copy classes in your project with same name.
Step2. Just create a GsonRequest Class as follows (taken from https://developer.android.com/training/volley/request-custom.html)
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));
}
}
Step3.Now in your main Activity just use this "GsonRequest" class like that:
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
GsonRequest<MyPojoClass> gsonRequest = new GsonRequest<MyPojoClass>(
Request.Method.GET,
apiurl,
MyPojoClass.class,
mySuccessListener(),
myErrorListener());
//Add below these code lines for "Retry" data fetching from api
gsonRequest.setRetryPolicy(new DefaultRetryPolicy(
5000,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
mRequestQueue.add(gsonRequest);
}
private Response.Listener<MyPojoClass> mySuccessListener() {
return new Response.Listener<CustomRequest>() {
#Override
public void onResponse(MyPojoClass pRequest) {
//do something
}
};
}
private Response.ErrorListener myErrorListener() {
return new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
System.out.println(volleyError.getMessage().toString());
}
};
}
Related
I have created an abstract request to make it easier to send requests.
abstract class MyRequest<T> extends Request<T> {
private final static String API_KEY = "";
private final static String API_STRING = "?api_key=";
private final Class<T> objectType;
private final Response.Listener<T> listener;
public MyRequest(String url, Class<T> objectType, Response.Listener<T> listener, #Nullable Response.ErrorListener errorListener) {
super(Method.GET, url + API_STRING + API_KEY, errorListener);
this.objectType = objectType;
this.listener = listener;
}
#Override
protected Response<T> parseNetworkResponse(NetworkResponse response) {
try {
return Response.success(Mapper.getMapper().readValue(new String(response.data, HttpHeaderParser.parseCharset(response.headers)), objectType),
HttpHeaderParser.parseCacheHeaders(response));
} catch (IOException e) {
return Response.error(new ParseError(e));
}
}
#Override
protected void deliverResponse(T response) {
listener.onResponse(response);
}
}
This code is used to make a custom request like this:
public class MasteryRequest extends MyRequest<Summoner> {
private static final String URL = "https://euw1.api.riotgames.com/lol/champion-mastery/v4/champion-masteries/by-summoner/";
public MasteryRequest(String summonerId, Response.Listener<Summoner> listener, #Nullable Response.ErrorListener errorListener) {
super(URL + summonerId, Summoner.class, listener, errorListener);
}
}
Now my problem is the API returns an array of objects and jackson is unable to convert that into my Summoner object. The summoner object looks like this:
public class Summoner {
private List<MasteryChampion> masteryChampions;
public List<MasteryChampion> getMasteryChampions() {
return masteryChampions;
}
}
It seems like jackson doesn't know how to put the return value into the array of summoner. Is there any annotation that I am missing so jackson knows how to put the array into summoner?
Response body example:
[
{
"championId": 92,
"championLevel": 7,
"championPoints": 1029885,
"lastPlayTime": 1653428885000,
"championPointsSinceLastLevel": 1008285,
"championPointsUntilNextLevel": 0,
"chestGranted": true,
"tokensEarned": 0,
"summonerId": "03tFEbQfU5-pL1y8xR0XBckv6bJx1M6OtfVe8WKQtc-_AFc"
},
{
"championId": 114,
"championLevel": 7,
"championPoints": 274271,
"lastPlayTime": 1653418873000,
"championPointsSinceLastLevel": 252671,
"championPointsUntilNextLevel": 0,
"chestGranted": true,
"tokensEarned": 0,
"summonerId": "03tFEbQfU5-pL1y8xR0XBckv6bJx1M6OtfVe8WKQtc-_AFc"
}
]
How to send multiple q input texts? As I see, the API doesn't allow q[] type arrays, instead it uses multiple q parameters.
protected Map<String,String> getParams(){
List<String> textString = new ArrayList<>();
Map<String,String> params = new HashMap<String, String>();
params.put("key", "key");
params.put("target", "DE");
params.put("q", text);
return params;
}
};
I found the following helper class:
class HttpParams extends HashMap<String, List<String>> {
private static final long serialVersionUID = 1L;
public HttpParams() {
super();
}
public HttpParams(int capacity) {
super(capacity);
}
public HttpParams(Map<String, List<String>> map) {
super(map);
}
public HttpParams(int capacity, float loadFactor) {
super(capacity, loadFactor);
}
/*
* This is the method to use for adding post parameters
*/
public void add(String key, String value) {
if (containsKey(key)) {
get(key).add(value);
}
else {
ArrayList<String> list = new ArrayList<String>();
list.add(value);
put(key, list);
}
}
/**
* Converts the Map into an application/x-www-form-urlencoded encoded string.
*/
public byte[] encodeParameters(String paramsEncoding) {
StringBuilder encodedParams = new StringBuilder();
try {
for (Map.Entry<String, List<String>> entry : entrySet()) {
String key = URLEncoder.encode(entry.getKey(), paramsEncoding);
for (String value : entry.getValue()) {
encodedParams.append(key);
encodedParams.append('=');
try {
encodedParams.append(URLEncoder.encode(value, paramsEncoding));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
encodedParams.append('&');
}
}
return encodedParams.toString().getBytes(paramsEncoding);
} catch (UnsupportedEncodingException uee) {
throw new RuntimeException("Encoding not supported: " + paramsEncoding, uee);
}
}
}
and then in Main class that extends Request overrided the getBody():
public void volleyPost(String text,OnServiceResponseListener onServiceResponseListener){
String URL = "Your Url here";
RequestQueue requestQueue = Volley.newRequestQueue(this);
HttpParams mParams = new HttpParams();
mParams.add("key", "key");
mParams.add("target", "languageCode");
String wordsArray [] = text.split(",");
for(int i = 0;i<wordsArray.length;i++) {
mParams.add("q", wordsArray[i]);
}
StringRequest stringRequest = new StringRequest(Request.Method.POST, URL,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
onServiceResponseListener.onSuccess(response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
onServiceResponseListener.onFailed(error.getMessage());
}
}){
#Override
public byte[] getBody() throws AuthFailureError {
if (mParams != null && mParams.size() > 0) {
Log.d(TAG,"mParams--->"+new Gson().toJson(mParams));
return mParams.encodeParameters(getParamsEncoding());
}
return null;
}
};
requestQueue.add(stringRequest);
}
I am using springboot 2x. Our project is using a Custom HttpServeletRequest which extends HttpServletRequestWrapper and implements MultipartHttpServletRequest. Everything works fine. But when I want to work for file upload, it can't initialized Multipart request. It shows error :
java.lang.IllegalStateException: Multipart request not initialized
My question is, how can I solve this error. How Multipart request will be initialized.
I am giving all code regarding this.
public class XHttpServletRequest extends HttpServletRequestWrapper implements MultipartHttpServletRequest {
public XHttpServletRequest (HttpServletRequest request) {
super(request);
}
private MultiValueMap<String, MultipartFile> multipartFiles;
private String method;
#Override
public String getMethod() {
if (this.method == null) return super.getMethod();
return this.method;
}
public void setMethod(String method) {
this.method = method;
}
private Map<String,String[]> parameters = new LinkedHashMap<String,String[]>();
public void setParameter(String name, String value) {
parameters.put(name, new String[] {value});
}
#Override
public String getParameter(String name) {
if (parameters.get(name) != null) {
return parameters.get(name)[0];
}
HttpServletRequest req = (HttpServletRequest) super.getRequest();
return req.getParameter(name);
}
public Map<String, String[]> getParameterMap() {
Map<String, String[]> result = new LinkedHashMap<String, String[]>();
result.putAll(super.getRequest().getParameterMap());
result.putAll(parameters);
return Collections.<String, String[]>unmodifiableMap(result);
}
public Enumeration<String> getParameterNames() {
Set<String> result = new LinkedHashSet<String>(Collections.list(super.getRequest().getAttributeNames()));
result.addAll(parameters.keySet());
return new Vector<String>(result).elements();
}
public String[] getParameterValues(String name) {
if (parameters.get(name) != null) {
return parameters.get(name);
}
HttpServletRequest req = (HttpServletRequest) super.getRequest();
return req.getParameterValues(name);
}
#Override
public HttpServletRequest getRequest() {
return (HttpServletRequest) super.getRequest();
}
#Override
public HttpMethod getRequestMethod() {
return HttpMethod.resolve(getRequest().getMethod());
}
#Override
public HttpHeaders getRequestHeaders() {
HttpHeaders headers = new HttpHeaders();
Enumeration<String> headerNames = getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
headers.put(headerName, Collections.list(getHeaders(headerName)));
}
return headers;
}
#Override
public HttpHeaders getMultipartHeaders(String s) {
return null;
}
#Override
public Iterator<String> getFileNames() {
return getMultipartFiles().keySet().iterator();
}
#Override
public MultipartFile getFile(String name) {
return getMultipartFiles().getFirst(name);
}
#Override
public List<MultipartFile> getFiles(String name) {
List<MultipartFile> multipartFiles = getMultipartFiles().get(name);
if (multipartFiles != null) {
return multipartFiles;
}
else {
return Collections.emptyList();
}
}
#Override
public Map<String, MultipartFile> getFileMap() {
return getMultipartFiles().toSingleValueMap();
}
#Override
public MultiValueMap<String, MultipartFile> getMultiFileMap() {
return getMultipartFiles();
}
#Override
public String getMultipartContentType(String s) {
return null;
}
/**
* Set a Map with parameter names as keys and list of MultipartFile objects as values.
* To be invoked by subclasses on initialization.
*/
protected final void setMultipartFiles(MultiValueMap<String, MultipartFile> multipartFiles) {
this.multipartFiles =
new LinkedMultiValueMap<>(Collections.unmodifiableMap(multipartFiles));
}
/**
* Obtain the MultipartFile Map for retrieval,
* lazily initializing it if necessary.
* #see #initializeMultipart()
*/
protected MultiValueMap<String, MultipartFile> getMultipartFiles() {
if (this.multipartFiles == null) {
initializeMultipart();
}
return this.multipartFiles;
}
/**
* Lazily initialize the multipart request, if possible.
* Only called if not already eagerly initialized.
*/
protected void initializeMultipart() {
throw new IllegalStateException("Multipart request not initialized");
}
}
Another class extends XHttpServletRequest and this is instead of HttpServeletRequest in our project. The following code:
public class YHttpRequest extends MutableHttpServletRequest {
private ByteArrayOutputStream cachedBytes;
public YHttpRequest(HttpServletRequest request) {
super(request);
}
#Override
public ServletInputStream getInputStream() throws IOException {
if (cachedBytes == null)
cacheInputStream();
return new CachedServletInputStream();
}
#Override
public BufferedReader getReader() throws IOException{
return new BufferedReader(new InputStreamReader(getInputStream()));
}
private void cacheInputStream() throws IOException {
/* Cache the inputstream in order to read it multiple times. For
* convenience, I use apache.commons IOUtils
*/
cachedBytes = new ByteArrayOutputStream();
IOUtils.copy(super.getInputStream(), cachedBytes);
}
public List<Map<String, Object>> getListData() throws RequestException {
List<Map<String, Object>> data = new ArrayList<>();
try {
ObjectMapper mapper = new ObjectMapper();
data = mapper.readValue(this.getInputStream(), new TypeReference<ArrayList<LinkedHashMap>>(){});
System.out.println(data);
}
catch (Exception e) {
// System.out.println(e.)
throw new RequestException("Unable to parse request data", e);
}
return data;
}
private Object cachedData = null;
public Object getRawData() throws RequestException {
Object data = new LinkedHashMap<>();
try {
ObjectMapper mapper = new ObjectMapper();
// data = mapper.readValue(this.getInputStream());
try {
data = mapper.readValue(this.getInputStream(), new TypeReference<HashMap>() {
});
}
catch (JsonMappingException e) {
// e.printStackTrace();
}
try {
data = mapper.readValue(this.getInputStream(), new TypeReference<List<HashMap>>() {
});
}
catch (JsonMappingException e) {
// e.printStackTrace();
}
System.out.println(data);
}
catch (Exception e) {
// System.out.println(e.)
throw new RequestException("Unable to parse request data", e);
}
return data;
}
public Object getData() throws RequestException {
if (this.cachedData == null) {
this.cachedData = this.getRawData();
}
return this.cachedData;
}
/* An inputstream which reads the cached request body */
public class CachedServletInputStream extends ServletInputStream {
private ByteArrayInputStream input;
public CachedServletInputStream() {
/* create a new input stream from the cached request body */
input = new ByteArrayInputStream(cachedBytes.toByteArray());
}
#Override
public boolean isFinished() {
return input.available() == 0;
}
#Override
public boolean isReady() {
return true;
}
#Override
public void setReadListener(ReadListener readListener) {
// throw new IOException("zubair says: Method not implemented in Cached Servlet Input Stream class");
}
#Override
public int read() throws IOException {
return input.read();
}
}
// Storage for Path variable
private Map<String, Object> pathVariableMap = null;
public Map<String, Object> getPathVariableMap() {
if (this.pathVariableMap == null) {
this.pathVariableMap = new LinkedHashMap<>();
this.pathVariableMap.putAll((Map<? extends String, ?>) this.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE));
}
return this.pathVariableMap;
}
public Object getPathVariable(String key) {
return this.getPathVariableMap().get(key);
}
public FurinaHttpRequest setPathVariable(String key, Object value) {
this.getPathVariableMap().put(key, value);
return this;
}
public FurinaHttpRequest clearPathVariableMap() {
this.getPathVariableMap().clear();
return this;
}
}
The controller code:
public String handleFileUpload(YHttpRequest request) {
if (request.getMethod().equalsIgnoreCase("GET")){
return "{}";
}
Map<String, MultipartFile> file= request.getFileMap();
try {
for(Map.Entry<String, MultipartFile> entry : file.entrySet()){
storageService.store(entry.getValue());
//model.addAttribute("message", "You successfully uploaded " + entry.getValue().getOriginalFilename() + "!");
files.add(entry.getValue().getOriginalFilename());
}
} catch (Exception e) {
//model.addAttribute("message", "FAIL to upload !");
}
return "{}";
}
This will work
public String handleFileUpload(YHttpRequest request) {
if (request.getMethod().equalsIgnoreCase("GET")){
return "{}";
}
StandardMultipartHttpServletRequest standardMultipartHttpServletRequest = new StandardMultipartHttpServletRequest(request);
Map<String, MultipartFile> file= request.getFileMap();
try {
for(Map.Entry<String, MultipartFile> entry : file.entrySet()){
storageService.store(entry.getValue());
//model.addAttribute("message", "You successfully uploaded " + entry.getValue().getOriginalFilename() + "!");
files.add(entry.getValue().getOriginalFilename());
}
} catch (Exception e) {
//model.addAttribute("message", "FAIL to upload !");
}
return "{}";
}
I am using Volley to fetch data from a REST service. So there are two methods , One is POST which creates an object on server and other is PUT which basically updates the same object.I use the same code for making these requests.I just change the Method which is passed in Volley.The app works fine through POST request with the correct data sent in the body, but it encounters a problem with PUT request where it randomly sends no data in the body.
I shifted to a custom Request object as suggested by Google but it is still not working.
int method = Request.Method.POST;
String objID = sharedPreferences.getString("objID", null);
String Url = "/api_url";
if (objID != null)
{
Url += objID + "/";
method = Request.Method.PUT;
}
try
{
JSONObject objJSON = new JSONObject();
objJSON.put("name", "new_name");
}
catch (JSONException e)
{
// Handle Execption
}
GsonRequest request = new GsonRequest<CustomObj>(method, Url, CustomObj.class,null, null, objJSON.toString(),
new Response.Listener<CustomObj>()
{
#Override
public void onResponse(CartObj cartObj)
{
// Handling Logic
}
}
,
new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError volleyError)
{
// Handle Error
}
});
VolleySingleton.getInstance(this).addToRequestQueue(request);
GsonRequest is my Custom Class Extending Request Object
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;
private final Map<String, String> params;
private final String body;
private ErrorListener mErrorListener;
/**
* 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(int method, String url, Class<T> clazz, Map<String, String> headers, Map<String, String> params, String body, Listener<T> listener, ErrorListener errorListener)
{
super(method, url, errorListener);
this.clazz = clazz;
this.headers = headers;
this.listener = listener;
this.params = params;
this.body = body;
this.mErrorListener = errorListener;
}
public GsonRequest(int method, String url, Class<T> clazz, Map<String, String> headers, Map<String, String> params, Listener<T> listener, ErrorListener errorListener)
{
this(method, url, clazz, headers, params, null, listener, errorListener);
}
public GsonRequest(int method, String url, Class<T> clazz, Map<String, String> headers, Listener<T> listener, ErrorListener errorListener)
{
this(method, url, clazz, headers, null, null, listener, errorListener);
}
#Override
public byte[] getBody() throws AuthFailureError
{
return body != null ? body.getBytes() : super.getBody();
}
#Override
protected Map<String, String> getParams() throws AuthFailureError
{
return params != null ? params : super.getParams();
}
#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 void deliverError(VolleyError error)
{
mErrorListener.onErrorResponse(error);
}
#SuppressWarnings("unchecked")
#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 GSON to parse my Data , and CustomObj is a Mapping Object for volley.
First of all all make sure the url you're building (where you check if objID is not null) is correct.
Secondly, you can try to call getBytes() method with a charset.
In the request override getBody() method:
#Override
public byte[] getBody() throws AuthFailureError {
try {
return body != null ? body.getBytes(getParamsEncoding()) : super.getBody();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return super.getBody();
}
Hope this will help.
Edit:
You can also try to override getBodyContentType() method:
#Override
public String getBodyContentType() {
return "application/json; charset=" + getParamsEncoding();
}
I am trying to make a Gson request using android volley. Currently it it working correctly and I am very happy. However why I try and get a List<> or a collection of objects my code no longer works.
Current code:
public class ReviewModel
{
public long Id;
public Strring Description;
}
here is how I use my gson class:
GsonRequest<ReviewModel> jsObjRequest = new GsonRequest<ReviewModel>(Request.Method.GET,
url, ReviewModel.class, new Response.Listener<ReviewModel>() {
#Override
public void onResponse(ReviewModel response) {
ReviewsHandleOkResponse(response);
}
}, new ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
ReviewsHandleErrorResponse(error);
}
});
Network.getInstance(getActivity()).addToRequestQueue(jsObjRequest);
}
here is my Volley GSON Request Class:
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 Map<String, String> params;
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(int method, String url, Class<T> clazz,
Map<String, String> headers, Map<String, String> params,
Listener<T> listener, ErrorListener errorListener) {
super(method, Network.getFullUrl(url), errorListener);
this.clazz = clazz;
this.headers = headers;
this.params = params;
this.listener = listener;
}
/**
* Recieves header
*
* #param method
* #param url
* #param clazz
* #param params
* #param listener
* #param errorListener
*/
public GsonRequest(int method, String url, Class<T> clazz,
Map<String, String> params, Listener<T> listener,
ErrorListener errorListener) {
super(method, Network.getFullUrl(url), errorListener);
this.clazz = clazz;
this.headers = new HashMap<String, String>();
this.params = params;
this.listener = listener;
}
/**
* No params or headers
*
* #param method
* #param url
* #param clazz
* #param listener
* #param errorListener
*/
public GsonRequest(int method, String url, Class<T> clazz,
Listener<T> listener, ErrorListener errorListener) {
super(method, Network.getFullUrl(url), errorListener);
this.clazz = clazz;
this.headers = new HashMap<String, String>();
this.params = new HashMap<String, String>();
this.listener = listener;
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
return headers != null ? headers : super.getHeaders();
}
#Override
public Map<String, String> getParams() throws AuthFailureError {
return params != null ? params : 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));
}
}
}
however when I rey and parse it to a List<ReviewModel> I get compile errors.
From what I have researched, I need to do some thing like :
Type collectionType = new TypeToken<ArrayList<ReviewModel>>(){}.getType();
// api/v1/reviews/products/{productId}/{pageNumber}/{pageSize}
String url = "api/v1/reviews/products/" + productId + "/" + currentPage + "/" + pageSize;
GsonRequest<ArrayList<ReviewModel>> jsObjRequest = new GsonRequest<ArrayList<ReviewModel>>(Request.Method.GET,
url, (Class<ArrayList<ReviewModel>>) collectionType, new Response.Listener<ArrayList<ReviewModel>>() {
#Override
public void onResponse(ArrayList<ReviewModel> response) {
ReviewsHandleOkResponse(response);
}
}, new ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
ReviewsHandleErrorResponse(error);
}
});
Network.getInstance(getActivity()).addToRequestQueue(jsObjRequest);
}
but this gives me the following error:
10-28 21:12:59.940: E/AndroidRuntime(28564):
java.lang.RuntimeException: Unable to start activity
ComponentInfo{com.menu/com.menu.activities.ProductViewActivity}:
java.lang.ClassCastException:
com.google.gson.internal.$Gson$Types$ParameterizedTypeImpl cannot be
cast to java.lang.Class
Do i need to modify my GsonRequest Class, and add another constructor which doesn't take a type class?
Use YourClass[] for List of objects in Volley request. It has solved my issue. The following code should help you:
GsonRequest<ReviewModel[]> jsObjRequest = new GsonRequest<ReviewModel[]>(Request.Method.GET,
url, ReviewModel[].class, new Response.Listener<ReviewModel[]>() {
#Override
public void onResponse(ReviewModel[] response) {
ReviewsHandleOkResponse(response);
}
}, new ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
ReviewsHandleErrorResponse(error);
}
});
Network.getInstance(getActivity()).addToRequestQueue(jsObjRequest);
}
I recently needed to implement a solution myself so here you go.
Custom GsonArrayRequest.
public class GsonArrayRequest<T> extends Request<ArrayList<T>> {
private final Gson gson = new Gson();
private final Class<T> clazz;
private final Map<String, String> headers;
private final Response.Listener<ArrayList<T>> listener;
/**
* Make a GET request and return a parsed object from JSON.
* #param clazz Relevant class object, for Gson's reflection
* #param url URL of the request to make
* #param headers Map of request headers
*/
public GsonArrayRequest(String url, Class<T> clazz, Map<String, String> headers,
Response.Listener<ArrayList<T>> listener, Response.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 Response<ArrayList<T>> parseNetworkResponse(NetworkResponse response) {
try {
String json = new String(
response.data,
HttpHeaderParser.parseCharset(response.headers));
Type listType = com.google.gson.internal.$Gson$Types.newParameterizedTypeWithOwner(null, ArrayList.class, clazz);
ArrayList<T> tList = gson.fromJson(json, listType);
return Response.success(
tList,
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JsonSyntaxException e) {
return Response.error(new ParseError(e));
}
}
#Override
protected void deliverResponse(ArrayList<T> response) {
listener.onResponse(response);
}
}
You can use it like this:
GsonArrayRequest<StoreWorkout> gsonArrayRequest = new GsonArrayRequest<>(
url, AngryPugs.class, null, new Response.Listener<ArrayList<AngryPugs>>() {
#Override
public void onResponse(ArrayList<AngryPugs> response) {
// your list here
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
After adding the request
VolleySingleton.getInstance(this).addToRequestQueue(gsonArrayRequest);