How to pass custom enum to @Query via Retrofit?

I have a simple enumeration:

public enum Season { @SerializedName("0") AUTUMN, @SerializedName("1") SPRING; } 

Starting some version, GSON was able to parse such transfers. To make sure I did this:

 final String s = gson.toJson(Season.AUTUMN); 

It works as I expected. The output signal is "0" . So I tried using it in my Retrofit services:

 @GET("index.php?page[api]=test") Observable<List<Month>> getMonths(@Query("season_lookup") Season season); /*...some files later...*/ service.getMonths(Season.AUTUMN); 

In addition, a magazine has been added to be sure of its result:

 HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(); httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient httpClient = new OkHttpClient.Builder() .addInterceptor(httpLoggingInterceptor) .build(); 

But it failed. @Query completely ignored by @SerializedName and .toString() used instead, so the log showed me .../index.php?page[api]=test&season_lookup=AUTUMN .

I followed the completion sources and found a RequestFactoryParser file with the lines:

 Converter<?, String> converter = retrofit.stringConverter(parameterType, parameterAnnotations); action = new RequestAction.Query<>(name, converter, encoded); 

It seems that this does not concern the enumerations at all. Before these lines, he tested rawParameterType.isArray() as an array or Iterable.class.isAssignableFrom() and nothing more.

Creating an instance of Retrofit:

 retrofit = new Retrofit.Builder() .baseUrl(ApiConstants.API_ENDPOINT) .client(httpClient) .addConverterFactory(GsonConverterFactory.create(gson)) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build(); 

gson GsonBuilder().create() . I looked at the sources, it has ENUM_TypeAdapters.ENUM_FACTORY predefined for listings, so I leave it as it is.


The question is, what can I do to prevent the use of toString() in my enums and use @SerializedName ? I use toString() for other purposes.

+6
source share
1 answer

As @ DawidSzydło mentioned, I misunderstood the use of Gson in Modification. It is used only for decoding / encoding a response / request, but not for @Query/@Url/@Path etc For them, Retrofit uses Converter.Factory to convert any type to String . Here is the code to automatically use @SerializedName as the value of any Enum when passing it to Retrofit services.

Converter

 public class EnumRetrofitConverterFactory extends Converter.Factory { @Override public Converter<?, String> stringConverter(Type type, Annotation[] annotations, Retrofit retrofit) { Converter<?, String> converter = null; if (type instanceof Class && ((Class<?>)type).isEnum()) { converter = value -> EnumUtils.GetSerializedNameValue((Enum) value); } return converter; } } 

EnumUtils:

 public class EnumUtils { @Nullable static public <E extends Enum<E>> String GetSerializedNameValue(E e) { String value = null; try { value = e.getClass().getField(e.name()).getAnnotation(SerializedName.class).value(); } catch (NoSuchFieldException exception) { exception.printStackTrace(); } return value; } } 

Retrofit creation:

 retrofit = new Retrofit.Builder() .baseUrl(ApiConstants.API_ENDPOINT) .client(httpClient) .addConverterFactory(GsonConverterFactory.create(gson)) .addConverterFactory(new EnumRetrofitConverterFactory()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build(); 
+7
source

All Articles