我在我的应用程序中使用了reverfit(V2.9.0)和Moshi(V1.11.0)。我尝试这样调用endpoint:
@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>
但是WatchStatus->JSON转换没有像预期的那样工作。WatchStatus是一个简单的枚举类:
enum class WatchStatus {
COMPLETED,
DROPPED,
ON_HOLD,
PLAN_TO_WATCH,
WATCHING,
}
我创建了一个自定义适配器,因为我的应用程序使用大写枚举名称,而后端使用小写名称:
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实例:
Moshi.Builder()
.addLast(KotlinJsonAdapterFactory())
.add(AnimeMoshiAdapters())
.build()
并且我的改型实例使用它(带有Koin注入):
Retrofit.Builder()
.baseUrl(get<String>(named("baseUrl")))
.client(get(named("default")))
.addConverterFactory(MoshiConverterFactory.create(get()))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
解析Json以创建WatchStatus枚举时,将使用适配器。这是很明显的,因为如果我移除自定义适配器,调用失败并出现错误“com.squareup.moshi.jsonDataException:Expected one of[COMPLETED,drop,ON_HOLD,PLAN_TO_WATCH,wating]”。当我试图调用上面指定的endpoint时,Json中WatchStatus的转换是错误的,枚举名保持大写,这意味着没有使用我的自定义适配器。如果我检查修改日志,我可以看到它发送“num_watched_episodes=12&score=6.0&status=on_hold”,所以状态不是用小写转换的。
如果我尝试使用相同的Moshi实例手动转换Json中的WatchStatus,它会按照预期工作,因此我相信我的自定义适配器实现是正确的。
我如何在这个调用中使用我的自定义Moshi适配器?
Moshi适配器的tojson
应用于改装请求的主体(==带有@body
注释的params),而不是查询参数(==带有@field
注释的params)。这是正确的和预期的行为,因为按照标准,查询参数不期望是JSON格式的字符串(即使在您的例子中,它只是一个字符串)。如果您的服务器希望status
字段作为查询参数,那么除了自己提供小写字段之外,没有其他方法:
@FormUrlEncoded
@PATCH("anime/{anime_id}/my_list_status")
fun updateListStatus(
...
@Field("status") watchStatus: String
): Single<MyListStatus>
并向updateListStatus
提供已经小写的值:
updateListStatus(..., COMPLETED.name.toLowerCase())
如果您对服务器的实现没有影响,那么就跳过这篇文章的其余部分。
如果希望利用自定义适配器的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>
在这种情况下,您的自定义适配器将生效并通过其定义的ToJSON
逻辑转换RequestBody
内部的WatchStatus
。
在为Android项目配置Kotlin之后,我编写了一个简单的。它调用了reverfit来获得一个包含以下数据的JSON文件: 现在我想使用Moshi将JSON数据转换为Kotlin的类,所以下面是反映上述JSON结构的两个类: 和Moshi的自定义类型适配器: 当它进入函数时,就像预期的那样。但奇怪的是,是,应该是。 我对莫希和科特林是新的,我已经在这个问题上坚持了大约10个小时。请帮帮我。谢谢
我使用一个API,它以数组的形式返回数据,比如这个JSON字符串(我们称之为“任务”) 我想将这个响应解析为一个列表。所以我已经用生成的适配器创建了相应的数据类 我的改装服务是这样的 但我想使用容器类型,例如: 作为网络响应结果。这可能不创建自定义adpter或者我将需要创建一个自定义适配器并将其传递给moshi构建器吗?
让我们看看一个需要诉诸于代码的场景,来考虑为何此时使用枚举更为合适且实用。假设我们要处理 IP 地址。目前被广泛使用的两个主要 IP 标准:IPv4(version four)和 IPv6(version six)。这是我们的程序可能会遇到的所有可能的 IP 地址类型:所以可以 枚举 出所有可能的值,这也正是此枚举名字的由来。 任何一个 IP 地址要么是 IPv4 的要么是 IPv6 的,而且不能
enum 关键字允许创建一个代表数个可能变量的数据的类型(原文:The enum keyword allows the creation of a type which may be one of a few different variants.若您对此句有 更好的翻译或理解,希望指出来,谢谢。)。在 struct 中任何合法的变量在 enum 同样是合法的。 // 隐藏未使用代码警告的属性。
问题内容: 我想要一个Java枚举,其值是整数。 例如: 但是我也想要这两个常量的自定义名称, 例如“ Task Created”和“ Task Deleted”(那里有空格)。 我想尽可能优雅地做到这一点,而无需编写 太多额外的代码。 我可以在没有其他 将枚举常量映射到其自定义名称的映射的情况下实现此目标吗? 我在该项目中使用JDK 6。 问题答案: 只需为此添加一个字段: 如果您不想指定字符串
在不使用其他映射( 将枚举常量映射到它们的自定义名称)的情况下,我能做到这一点吗? 我在这个项目中使用JDK6。