Last active
January 12, 2018 12:43
-
-
Save chantellosejo/6ff7e377ae6fcdb0c78f to your computer and use it in GitHub Desktop.
Custom request that parses Json into Java objects using Gson
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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