Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/218.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android @FormUrlEncoded@Field枚举未使用自定义Moshi适配器_Android_Json_Enums_Retrofit_Moshi - Fatal编程技术网

Android @FormUrlEncoded@Field枚举未使用自定义Moshi适配器

Android @FormUrlEncoded@Field枚举未使用自定义Moshi适配器,android,json,enums,retrofit,moshi,Android,Json,Enums,Retrofit,Moshi,我在我的应用程序中使用改型(v2.9.0)和Moshi(v1.11.0)。我尝试以这种方式调用端点: @FormUrlEncoded @PATCH("anime/{anime_id}/my_list_status") fun updateListStatus( @Path("anime_id") animeId: Long, @Field("num_watched_episodes") nbWatchedEpisodes

我在我的应用程序中使用改型(v2.9.0)和Moshi(v1.11.0)。我尝试以这种方式调用端点:

@FormUrlEncoded
@PATCH("anime/{anime_id}/my_list_status")
fun updateListStatus(
    @Path("anime_id") animeId: Long,
    @Field("num_watched_episodes") nbWatchedEpisodes: Int,
    @Field("score") score: Double,
    @Field("status") watchStatus: WatchStatus,
): Single<MyListStatus>
Moshi.Builder()
        .addLast(KotlinJsonAdapterFactory())
        .add(AnimeMoshiAdapters())
        .build()
我创建了一个自定义适配器,因为我的应用程序使用大写枚举名,而后端使用小写名称:

class AnimeMoshiAdapters {

    /* Others adapters */

    @ToJson
    fun watchStatusToJson(watchStatus: WatchStatus): String = 
watchStatus.toString().toLowerCase(Locale.getDefault())

    @FromJson
    fun watchStatusFromJson(watchStatus: String): WatchStatus =
        WatchStatus.valueOf(watchStatus.toUpperCase(Locale.getDefault()))
}
我通过以下方式创建我的Moshi实例:

@FormUrlEncoded
@PATCH("anime/{anime_id}/my_list_status")
fun updateListStatus(
    @Path("anime_id") animeId: Long,
    @Field("num_watched_episodes") nbWatchedEpisodes: Int,
    @Field("score") score: Double,
    @Field("status") watchStatus: WatchStatus,
): Single<MyListStatus>
Moshi.Builder()
        .addLast(KotlinJsonAdapterFactory())
        .add(AnimeMoshiAdapters())
        .build()
我的改造实例使用它(使用Koin注入):

reformation.Builder()
.baseUrl(获取(命名为(“baseUrl”))
.client(获取(命名为(“默认”))
.addConverterFactory(MoshiConverterFactory.create(get())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
解析Json以创建WatchStatus枚举时,将使用适配器。这是显而易见的,因为如果我删除自定义适配器,调用将失败,并出现错误“com.squareup.moshi.JsonDataException:预期为[COMPLETED,droped,ON_HOLD,PLAN_TO_WATCH,WATCHING]”。 当我尝试调用上面指定的端点时,Json中WatchStatus的转换是错误的,枚举名保持大写,这意味着没有使用我的自定义适配器。如果我查看改装日志,我可以看到它发送“num_wasted_stitues=12&score=6.0&status=ON_HOLD”,因此状态不会转换为小写

如果我尝试使用相同的Moshi实例手动转换Json中的WatchStatus,它将按预期工作,因此我相信我的自定义适配器实现是正确的


如何在此调用中使用自定义Moshi适配器进行改装?

Moshi适配器的
toJson
应用于改装请求的主体(=用
@body
注释的参数),而不是查询参数(=用
@FIELD
注释的参数)。这是正确的和预期的行为,因为查询参数按标准不应是JSON格式的字符串(尽管在您的例子中它只是一个字符串)。如果您的服务器希望
status
字段作为查询参数,那么除了自己提供小写字段外,没有其他方法:

@FormUrlEncoded
@PATCH("anime/{anime_id}/my_list_status")
fun updateListStatus(
    ...
    @Field("status") watchStatus: String
): Single<MyListStatus>
如果您对服务器的实现没有影响,那么跳过本文的其余部分

如果要利用自定义适配器的
toJson
函数,服务器需要更改请求以接受JSON正文而不是查询参数,如下所示:

PUT: anime/{anime_id}/my_list_status
BODY:
{
  "anime_id" : Long,
  "num_watched_episodes" : Int,
  "score" : Double,
  "status" : WatchStatus
}
然后,您将为主体创建一个数据类,例如命名为
RequestBody
,然后您可以将请求更改为:

@PUT("anime/{anime_id}/my_list_status")
fun updateListStatus(
    ...
    @BODY body: RequestBody
): Single<MyListStatus>
@PUT(“动画/{anime\u id}/my\u list\u status”)
趣味updateListStatus(
...
@主体:请求主体
):单身

在这种情况下,您的自定义适配器将生效,并通过其定义的
toJson
逻辑来转换
RequestBody
中的
WatchStatus

感谢您的解释,这完全有意义。为了将jsonWatchStatus解析保持在一个地方,我在我的存储库中重用了Moshi适配器:AnimeMoshiAdapters().watchStatusToJson(listStatus.status),它可以按需要工作。
@PUT("anime/{anime_id}/my_list_status")
fun updateListStatus(
    ...
    @BODY body: RequestBody
): Single<MyListStatus>