// Copyright 2015 The Project Buendia Authors // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy // of the License at: http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software distrib- // uted under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES // OR CONDITIONS OF ANY KIND, either express or implied. See the License for // specific language governing permissions and limitations under the License. package org.projectbuendia.client.net; import com.android.volley.AuthFailureError; import com.android.volley.NetworkResponse; import com.android.volley.ParseError; import com.android.volley.Request; import com.android.volley.Response; import com.android.volley.toolbox.HttpHeaderParser; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonSyntaxException; import org.apache.http.protocol.HTTP; import java.io.UnsupportedEncodingException; import java.lang.reflect.Type; import java.util.Map; import javax.annotation.Nullable; /** A {@link Request} with a JSON response parsed by {@link Gson}. */ public class GsonRequest<T> extends Request<T> { private final GsonBuilder mGson = new GsonBuilder(); private final Type mType; private final Map<String, String> mHeaders; private final Response.Listener<T> mListener; private Map<String, String> mBody = null; /** * Makes a GET request and returns a parsed object from JSON. * @param url URL of the request to make * @param type The type of the base response JSON object. Gson reflects on this * parameter to create the response object. Note that in most situations, * using {@code MyJsonResponseType.class} will work, but if your response * object makes use of generics, you will need to generate a type from a * {@link com.google.gson.reflect.TypeToken TypeToken}, using something * like {@code new TypeToken<MyJsonResponseType<SubType>>{}.getType()}. * @param headers Map of request headers * @param listener a {@link Response.Listener} that handles successful requests * @param errorListener a {@link Response.ErrorListener} that handles failed requests */ public GsonRequest(String url, Type type, Map<String, String> headers, Response.Listener<T> listener, Response.ErrorListener errorListener) { this(Method.GET, null, url, type, headers, listener, errorListener); } /** * Makes a request using an arbitrary HTTP method and returns a parsed object from JSON. * @param method the request method * @param body the request body * @param url URL of the request to make * @param type The type of the base response JSON object. Gson reflects on this * parameter to create the response object. Note that in most situations, * using {@code MyJsonResponseType.class} will work, but if your response * object makes use of generics, you will need to generate a type from a * {@link com.google.gson.reflect.TypeToken TypeToken}, using something * like {@code new TypeToken<MyJsonResponseType<SubType>>{}.getType()}. * @param headers Map of request headers * @param listener a {@link Response.Listener} that handles successful requests * @param errorListener a {@link Response.ErrorListener} that handles failed requests */ public GsonRequest(int method, @Nullable Map<String, String> body, String url, Type type, Map<String, String> headers, Response.Listener<T> listener, Response.ErrorListener errorListener) { super(method, url, errorListener); this.mBody = body; this.mType = type; this.mHeaders = headers; this.mListener = listener; } @Override public Map<String, String> getHeaders() throws AuthFailureError { return mHeaders != null ? mHeaders : super.getHeaders(); } public GsonBuilder getGson() { return mGson; } @Override protected void deliverResponse(T response) { mListener.onResponse(response); } @Override protected Map<String, String> getParams() { return mBody; } @Override protected Response<T> parseNetworkResponse(NetworkResponse response) { try { String json = new String( response.data, HTTP.UTF_8); // TODO: HttpHeaderParser.parseCharset(response.mHeaders). Gson gsonParser = mGson.create(); //noinspection unchecked return (Response<T>) Response.success( gsonParser.fromJson(json, mType), HttpHeaderParser.parseCacheHeaders(response)); } catch (UnsupportedEncodingException e) { return Response.error(new ParseError(e)); } catch (JsonSyntaxException e) { return Response.error(new ParseError(e)); } catch (Exception e) { return Response.error(new ParseError(e)); } } }