android - Moshi:解析单个对象或对象列表 (kotlin)

标签 android json kotlin adapter moshi

问题

如何解析单个 Warning对象或 Warning 的列表使用 Moshi 来自 API 的对象 ( List<Warning> ) ?

作为单个警告的响应:

{
  "warnings": {...}
}

作为警告列表的响应:

{
  "warnings": [{...}, {...}]
}

反复试验

试图塞进一个自动生成的 Moshi适配器。试图在此基础上构建但失败了。

解决方案

工厂的通用方法

我尝试将 Eric 编写的适配器从 Java 翻译成 Kotlin,因为我意识到更通用的方法更好,就像 Eric 在他的回复中指出的那样。

一旦成功,我将修改这篇文章以使其更易于理解。抱歉,现在有点乱。

编辑:我最终使用了 solution Eric 在另一个线程中建议(翻译成 Kotlin)。

带工厂的适配器

package org.domain.name

import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.JsonQualifier
import com.squareup.moshi.JsonReader
import com.squareup.moshi.JsonWriter
import com.squareup.moshi.Moshi
import com.squareup.moshi.Types
import java.util.Collections
import java.lang.reflect.Type
import kotlin.annotation.AnnotationRetention.RUNTIME
import kotlin.annotation.AnnotationTarget.FIELD

class SingleToArrayAdapter(
    val delegateAdapter: JsonAdapter<List<Any>>,
    val elementAdapter: JsonAdapter<Any>
) : JsonAdapter<Any>() {

    companion object {
        val factory = 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) ?: return null
            if (Types.getRawType(type) !== List::class.java) throw IllegalArgumentException("Only List can 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.factory)
    .build()

引用

最佳答案

the API returns either 1 object if there is only 1 or > 1 a list of objects.

创建一个适配器,它可以查看您是否首先获得了一个数组。 Here正是你想要的。它包含一个限定符,因此您只能将它应用于可能对单个项目具有此行为的列表。 @SingleToArray List<Warning> .

还有一个处理多种格式的例子here进一步阅读。

关于android - Moshi:解析单个对象或对象列表 (kotlin),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53344033/

相关文章:

java - mainClassName的etter : String' is deprecated.在Java中已弃用

android - 改造通用响应处理程序

kotlin - 如何在 kotlin 中编写@Nested 测试类

java - 使用类添加 View 的预期类或包

json - 转换JSON文件时出现“Invalid JSON primitive”错误

java - 通过使用 Jackson API 动态发送 key 来检索 JSON 字符串中的值?

javascript - 为 d3 网络图添加选择框

android - Volley StringRequest 响应更改撇号的值(' 更改为 â)

java - 移动可绘制对象和 Imageview 布局的问题

java - fragment 旋转器不工作