我有一个简单的枚举:
public enum Season {
@SerializedName("0")
AUTUMN,
@SerializedName("1")
SPRING;
}
从某个版本开始,GSON就能够解析这样的枚举。
final String s = gson.toJson(Season.AUTUMN);
它和我预期的一样工作。输出是"0"
。所以,我试着在我的翻新服务中使用它:
@GET("index.php?page[api]=test")
Observable<List<Month>> getMonths(@Query("season_lookup") Season season);
/*...some files later...*/
service.getMonths(Season.AUTUMN);
此外,还添加了日志记录功能,以确保其结果的可靠性:
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient httpClient = new OkHttpClient.Builder()
.addInterceptor(httpLoggingInterceptor)
.build();
但是它失败了。@Query
完全忽略了@SerializedName
,而使用了.toString()
,所以日志显示了.../index.php?page[api]=test&season_lookup=AUTUMN
。
我追踪了Retrofit源代码,发现文件RequestFactoryParser
包含以下行:
Converter<?, String> converter =
retrofit.stringConverter(parameterType, parameterAnnotations);
action = new RequestAction.Query<>(name, converter, encoded);
看起来,它根本不关心枚举。在这些行之前,它测试rawParameterType.isArray()
是一个数组或Iterable.class.isAssignableFrom()
,仅此而已。
改造示例创建为:
retrofit = new Retrofit.Builder()
.baseUrl(ApiConstants.API_ENDPOINT)
.client(httpClient)
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
gson
是GsonBuilder().create()
。我看了一下源代码,里面有预定义的ENUM_TypeAdapters.ENUM_FACTORY
用于枚举,所以我保持原样。
问题是我可以做些什么,以防止在我的枚举上使用toString()
并使用@SerializedName
?我将toString()
用于其他目的。
2条答案
按热度按时间hec6srdp1#
正如@DawidSzydło提到的,我误解了
Gson
在Retrofit中的用法。它只用于响应/请求解码/编码,而不用于@Query/@Url/@Path e.t.c
。对于它们,Retrofit使用Converter.Factory
将任何类型转换为String
。下面是在将@SerializedName
传递给Retrofit服务时自动使用@SerializedName
作为任何Enum
的值。转换器:
枚举工具:
改造创造:
08.18更新添加Kotlin模拟:
在日志中,您将看到以下内容:
使用的相依性为:
rqenqsqc2#
如果不是所有枚举都需要它,我想您也可以跳过
Converter.Factory
设置,只添加一个toString
方法:或者,如果您需要它用于多个: