Last active
February 25, 2020 01:17
-
-
Save varunachar/e98a2c240eddc56053c5 to your computer and use it in GitHub Desktop.
Google Gson TypeAdapterFactory to use with Retrofit when the the object is nested inside another object (Typically an object which contains status code etc) and when the root changes per object like shown below in the sample ANestedObject.json. Then you can use Retrofit normally! Enjoy
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
// Root is hotel | |
{ | |
status : "ok", | |
statusCode : 200, | |
hotels : [{ | |
name : "Taj Palace", | |
location : { | |
lat : 12 | |
lng : 77 | |
} | |
}, { | |
name : "Plaza", | |
location : { | |
lat : 12 | |
lng : 77 | |
} | |
}] | |
} | |
//Root is city | |
{ | |
status : "ok", | |
statusCode : 200, | |
city : { | |
name : "Bengaluru", | |
location : { | |
lat : 12 | |
lng : 77 | |
} | |
} | |
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.example.api; | |
import com.example.pojo.Hotel; | |
import com.example.pojo.City; | |
import java.util.List; | |
import retrofit.http.Body; | |
import retrofit.http.GET; | |
import retrofit.http.POST; | |
import retrofit.http.Path; | |
import retrofit.http.Query; | |
import rx.Observable; | |
/** | |
* Created by varunachar on 20/11/15. | |
*/ | |
public interface ApiService { | |
@GET("api/{id}") | |
Observable<City> city(@Path("id") String id); | |
@POST("hotel/nearby") | |
Observable<List<Hotel>> drivers(@Body Location location); | |
} |
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.example.pojos; | |
import com.example.pojos.Location; | |
import com.example.adapters.InnerKey; | |
@InnerKey("hotel") | |
public class Hotel { | |
private String name; | |
private Location location; | |
// getters, setters, other properties | |
} |
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.example.adapters; | |
import java.lang.annotation.ElementType; | |
import java.lang.annotation.Retention; | |
import java.lang.annotation.RetentionPolicy; | |
import java.lang.annotation.Target; | |
/** | |
* Created by varunachar on 20/11/15. | |
*/ | |
@Retention(RetentionPolicy.RUNTIME) | |
@Target(ElementType.TYPE) | |
public @interface InnerKey { | |
String value(); | |
} |
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.example.adapters; | |
import com.google.gson.TypeAdapter; | |
import com.google.gson.stream.JsonReader; | |
import com.google.gson.stream.JsonToken; | |
import com.google.gson.stream.JsonWriter; | |
import java.io.IOException; | |
/** | |
* Created by varunachar on 20/11/15. | |
*/ | |
public class ItemTypeAdapter<T> extends TypeAdapter<T> { | |
private final String root; | |
private TypeAdapter<T> delegate; | |
private boolean isList = false; | |
public ItemTypeAdapter(String root, TypeAdapter<T> delegate, boolean isList) { | |
this.root = root; | |
this.delegate = delegate; | |
this.isList = isList; | |
} | |
@Override | |
public void write(JsonWriter out, T value) throws IOException { | |
delegate.write(out, value); | |
} | |
@Override | |
public T read(JsonReader in) throws IOException { | |
if (in.peek() == JsonToken.NULL) { | |
in.nextNull(); | |
return null; | |
} | |
T obj = null; | |
// If not the parent object | |
if(!in.getPath().equalsIgnoreCase("$")){ | |
return delegate.read(in); | |
} | |
in.beginObject(); | |
while (in.hasNext()) { | |
if (root.equalsIgnoreCase(in.nextName())) { | |
if (isList) { | |
obj = delegate.read(in); | |
} else { | |
obj = delegate.read(in); | |
} | |
} | |
else { | |
in.skipValue(); | |
} | |
} | |
in.endObject(); | |
return obj; | |
} | |
} |
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.example.api; | |
import com.google.gson.Gson; | |
import com.google.gson.GsonBuilder; | |
import com.headlyt.adapters.TypeAdapterFactory; | |
import com.headlyt.utils.ApiConstants; | |
import com.headlyt.utils.CommonMethods; | |
import com.squareup.okhttp.HttpUrl; | |
import com.squareup.okhttp.OkHttpClient; | |
import com.squareup.okhttp.Request; | |
import retrofit.GsonConverterFactory; | |
import retrofit.Retrofit; | |
import retrofit.RxJavaCallAdapterFactory; | |
/** | |
* Created by varunachar on 20/11/15. | |
*/ | |
public class RestClient | |
{ | |
private ApiService apiService; | |
private static RestClient restClient = new RestClient(); | |
public static RestClient get() { | |
return restClient; | |
} | |
private RestClient() | |
{ | |
Gson gson = new GsonBuilder() | |
.setDateFormat("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'SSS'Z'") | |
.registerTypeAdapterFactory(new TypeAdapterFactory()) | |
.create(); | |
OkHttpClient client = new OkHttpClient(); | |
client.interceptors().add(chain -> { | |
Request request = chain.request(); | |
HttpUrl url = request.httpUrl().newBuilder().addQueryParameter("access_token", CommonMethods.getAccessToken()).build(); | |
request = request.newBuilder().url(url).build(); | |
return chain.proceed(request); | |
}); | |
Retrofit retrofit = new Retrofit.Builder().baseUrl(ApiConstants.API_URL) | |
.addConverterFactory(GsonConverterFactory.create(gson)) | |
.addCallAdapterFactory(RxJavaCallAdapterFactory.create()) | |
.client(client) | |
.build(); | |
apiService = retrofit.create(ApiService.class); | |
} | |
public ApiService api() | |
{ | |
return apiService; | |
} | |
} |
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.example.adapters; | |
import com.google.gson.Gson; | |
import com.google.gson.TypeAdapter; | |
import com.google.gson.reflect.TypeToken; | |
import java.lang.reflect.ParameterizedType; | |
import java.util.List; | |
/** | |
* Created by varunachar on 20/11/15. | |
*/ | |
public class TypeAdapterFactory implements com.google.gson.TypeAdapterFactory { | |
@Override | |
public <T> TypeAdapter<T> create(final Gson gson, TypeToken<T> type) { | |
TypeAdapter<T> adapter = gson.getDelegateAdapter(this, type); | |
if (type.getRawType().isAssignableFrom(List.class)) { | |
ParameterizedType parameterizedType = (ParameterizedType) type.getType(); | |
TypeToken<T> typeToken = (TypeToken<T>) TypeToken.get(parameterizedType.getActualTypeArguments()[0]); | |
TypeAdapter<T> elementAdapter = gson.getAdapter(typeToken); | |
if (typeToken.getRawType().isAnnotationPresent(InnerKey.class)) { | |
return new ItemTypeAdapter<>(typeToken.getRawType().getAnnotation(InnerKey.class).value().concat("s"), adapter, true); | |
} else { | |
return adapter; | |
} | |
} else { | |
if (!type.getRawType().isAnnotationPresent(InnerKey.class)) { | |
return adapter; | |
} | |
return new ItemTypeAdapter<>(type.getRawType().getAnnotation(InnerKey.class).value(), adapter, false); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment