我有这样的枚举:
enum class NewTaskState(val value: Int) {
@SerializedName("0")
STATE_INSTALLED(0),
@SerializedName("1")
STATE_LAUNCHED(1)
}
具有改进功能的API调用:
@POST("tasks/android/{id}/state/update/")
@FormUrlEncoded
fun updateAppTaskState(
@Path("id") id: Long,
@Query("device_pk") deviceId: Long,
@Field("new_state") newState: NewTaskState
): Single<Response<Any>>
和GSON配置:
return GsonBuilder()
.registerTypeAdapter(Date::class.java, DateDeserializer())
.enableComplexMapKeySerialization()
.create()
Gson版本为2.8.5
。
使用此通话时,我会在日志中看到:
I/OkHttp: --> POST <removed>/tasks/android/1/state/update/?device_pk=8
I/OkHttp: Content-Type: application/x-www-form-urlencoded
I/OkHttp: Content-Length: 25
I/OkHttp: Authorization: Token <removed>
I/OkHttp: new_state=STATE_INSTALLED
因此,它忽略序列化上的@SerializedName
值,但在反序列化上运行良好。
怎么了?
答案 0 :(得分:1)
发生这种情况是因为Gson
不参与url表单编码。
来自@Field
的javadoc:
使用
Retrofit.stringConverter(Type, Annotation[])
(或Object.toString()
,如果未安装匹配的字符串转换器)将值转换为字符串,然后形成URL编码。null
个值将被忽略。传递List
或数组将为每个非null
项目产生一个字段对。
并且GsonConverterFactory
不会覆盖Converter.Factory#stringConverter
,因此它不会忽略任何内容。只是不参加
作为解决方法,您可以执行类似的操作:
Converter
:
object EnumAsOrdinalToStringConverter : Converter<Enum<*>, String> {
override fun convert(value: Enum<*>): String =
value.ordinal.toString()
}
Factory
:
class EnumAsOrdinalToStringConverterFactory : Converter.Factory() {
override fun stringConverter(
type: Type,
annotations: Array<Annotation>,
retrofit: Retrofit
): Converter<*, String>? = if (type is Class<*> && type.isEnum) {
EnumAsOrdinalToStringConverter
} else {
null
}
}
建筑物Retrofit
:
addConverterFactory(EnumAsOrdinalToStringConverterFactory())