Skip to content

Instantly share code, notes, and snippets.

@chanakin
Last active January 12, 2018 12:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save chanakin/6ff7e377ae6fcdb0c78f to your computer and use it in GitHub Desktop.
Save chanakin/6ff7e377ae6fcdb0c78f to your computer and use it in GitHub Desktop.
Custom request that parses Json into Java objects using Gson
package com.myapp.android.network;
import android.net.Uri;
import android.support.annotation.CallSuper;
import android.util.Log;
import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Response;
import com.android.volley.toolbox.HttpHeaderParser;
import com.android.volley.toolbox.JsonRequest;
import com.myapp.android.BuildConfig;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
/**
* Created by Chantell Osejo on 3/13/15.
* This class encompasses a plain gson request to a http url. It assumes the response to be Json. It DOES NOT include any authentication for the request.
* Copyright (C) 2015 Chantell Osejo
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
public class GsonRequest<T> extends JsonRequest<T> {
private static final String ACCEPT = "Accept";
private static final String APPLICATION_JSON = "application/json";
private static final String NETWORK_REQUEST = "NetworkRequest";
private static final String CONTENT_TYPE = "Content-Type";
private static final String HTTPS = "https";
// I want to call special attention to the excludeFieldsWithoutExposeAnnotation() call below.
// If you are missing fields when the json is translated into a java object using gson, it's likely because you did
// not mark the field with the @Expose annotation. This was done intentionally to both make all variables apparent that
// could be used but will not cause excessive parsing for those that are not needed at this time (aka filtering out
// useless data from the server, if the server is sending more data than you care about as a client)
// Also feel free to registerTypeAdapter(CustomTypeAdapter.class, new CustomDeserializer()) here [Date is a good example]
private final Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
private final Class<T> clazz;
private final Map<String, String> headers;
private final Map<String, String> parameters;
/**
* @param url URL of the request to make
* @param clazz Relevant class object, for Gson's reflection
* @param headers Map of request headers
* @param parameters Map of request parameters (for POST and PUT only, DOES NOT WORK FOR GET)
* @param listener Listener to receive the response that contains the Gson object and a message
* @param errorListener Listener for errors associated with this request.
*/
public GsonRequest(int method, String url, Class<T> clazz, Map<String, String> headers, Map<String, String> parameters,
Response.Listener<T> listener, Response.ErrorListener errorListener, String json) {
super(method, getUrlWithParams(url, method, parameters), json, listener, errorListener);
this.clazz = clazz;
this.headers = null == headers ? new HashMap<String, String>() : headers;
this.parameters = parameters;
}
public GsonRequest(int method, String url, Class<T> clazz, Map<String, String> headers,
Response.Listener<T> listener, Response.ErrorListener errorListener) {
this(method, url, clazz, headers, null, listener, errorListener, null);
}
public GsonRequest(int method, String url, Class<T> clazz,
Response.Listener<T> listener, Response.ErrorListener errorListener) {
this(method, url, clazz, null, listener, errorListener);
}
private static String getUrlWithParams(String url, int method, Map<String, String> params) {
if (method != Method.GET) {
return url;
}
Uri.Builder builder = new Uri.Builder();
builder.scheme(HTTPS);
// This assumes in your build.gradle that you have specified a variable for URL AUTHORITY,
// i.e. buildTypes {
// debug {
// buildConfigField "String", "URL_AUTHORITY", "\"myapi.com\""
// }
// }
// This is super helpful if you have a beta API endpoint and a production one
builder.encodedAuthority(BuildConfig.URL_AUTHORITY);
builder.encodedPath(url);
if (null != params) {
for (String key : params.keySet()) {
try {
builder.appendQueryParameter(key, params.get(key));
} catch (Exception e) {
Log.e(NETWORK_REQUEST, "Error adding URL param: ", e);
}
}
}
// You can eliminate this variable if you don't want the log statement (but I find it helpful for debugging)
String fullUrl = builder.build().toString();
Log.i(NETWORK_REQUEST, "Generating request: method=" + getMethodString(method) + " url=" + fullUrl);
return fullUrl;
}
@Override
public String getBodyContentType() {
return APPLICATION_JSON;
}
@Override
@CallSuper
public Map<String, String> getHeaders() throws AuthFailureError {
headers.put(ACCEPT, APPLICATION_JSON);
headers.put(CONTENT_TYPE, APPLICATION_JSON);
return headers;
}
/**
* This ONLY gets called for POST and PUT requests. Therefore, if this is a GET request, we will add the parameters onto the URL in #link(getUrlWithParams)
*/
@Override
protected Map<String, String> getParams() throws AuthFailureError {
if (null == parameters) {
return super.getParams();
}
return parameters;
}
@Override
protected Response<T> parseNetworkResponse(NetworkResponse response) {
try {
final String json = new String(
response.data, HttpHeaderParser.parseCharset(response.headers));
return Response.success(gson.fromJson(json, clazz), null);
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JsonSyntaxException e) {
return Response.error(new ParseError(e));
}
}
private static String getMethodString(int method) {
switch (method) {
case Method.POST:
return "post";
case Method.PUT:
return "put";
case Method.DELETE:
return "delete";
case Method.HEAD:
return "head";
case Method.OPTIONS:
return "options";
case Method.TRACE:
return "trace";
case Method.PATCH:
return "patch";
case Method.DEPRECATED_GET_OR_POST:
case Method.GET:
default:
return "get";
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment