【发布时间】:2019-04-20 00:09:36
【问题描述】:
我正在构建一个应用程序,该应用程序可以从我无法控制的 API 中获取 Warning 对象,他们也不想删除我正在尝试解决的这种行为。
我希望能够解析单个 Warning 对象或 List<Warning> 对象。 (因为如果只有 1 个或 > 1 个对象列表,API 会返回 1 个对象。)
问题
如何直接将对象解析为列表或使用 Moshi 解析列表?
我得到的数据看起来像这样:
{
# List<Warning>
"warnings": [{...}, {...}]
}
或者像这样:
{
# Warning
"warnings": {...}
}
我已经阅读并找到了一些关于这个主题的资料,但没有示例,我不知道如何继续..所以任何指针都将受到高度赞赏。
尝试
我最初试图硬塞一个自动生成的 moshi 适配器,以为我可以在它之上构建,但我不知道发生了什么,所以它并没有真正引导我到任何地方。但是我还是包含了生成的代码,以防它仍然对任务有用。
编辑:这是我目前所拥有的,虽然我对需要一个 Moshi 实例才能工作这一事实不太满意。
解决方案
使用工厂的通用方法
我试图移植 Eric 写给 kotlin 的适配器 因为我已经意识到更通用的方法更好 埃里克在他的回复中指出。一旦这个工作正常,我将重写这篇文章的部分内容以使其更容易理解,现在有点混乱,我为此道歉。
编辑:我最终使用了另一个线程中建议的 solution Eric,但移植到了 Kotlin。
带工厂的适配器
class SingleToArrayAdapter(
val delegateAdapter: JsonAdapter<List<Any>>,
val elementAdapter: JsonAdapter<Any>
) : JsonAdapter<Any>() {
companion object {
val INSTANCE = SingleToArrayAdapterFactory()
}
override fun fromJson(reader: JsonReader): Any? =
if (reader.peek() != JsonReader.Token.BEGIN_ARRAY) {
Collections.singletonList(elementAdapter.fromJson(reader))
} else delegateAdapter.fromJson(reader)
override fun toJson(writer: JsonWriter, value: Any?) =
throw UnsupportedOperationException("SingleToArrayAdapter is only used to deserialize objects")
class SingleToArrayAdapterFactory : JsonAdapter.Factory {
override fun create(type: Type, annotations: Set<Annotation>, moshi: Moshi): JsonAdapter<Any>? {
val delegateAnnotations = Types.nextAnnotations(annotations, SingleToArray::class.java)
if (delegateAnnotations == null) return null
if (Types.getRawType(type) != List::class.java) throw IllegalArgumentException("Only lists may be annotated with @SingleToArray. Found: $type")
val elementType = Types.collectionElementType(type, List::class.java)
val delegateAdapter: JsonAdapter<List<Any>> = moshi.adapter(type, delegateAnnotations)
val elementAdapter: JsonAdapter<Any> = moshi.adapter(elementType)
return SingleToArrayAdapter(delegateAdapter, elementAdapter)
}
}
}
预选赛
注意:我必须添加Target(FIELD)。
@Retention(RUNTIME)
@Target(FIELD)
@JsonQualifier
annotation class SingleToArray
用法
用@SingleToArray注释您要确保解析为列表的字段。
data class Alert(
@SingleToArray
@Json(name = "alert")
val alert: List<Warning>
)
别忘了将适配器添加到您的 moshi 实例中:
val moshi = Moshi.Builder()
.add(SingleToArrayAdapter.INSTANCE)
.build()
相关问题/主题:
【问题讨论】:
标签: android json kotlin adapter moshi