android - 使用自定义 Gson 反序列化器反序列化 JSON 响应时出错

标签 android kotlin gson retrofit2 json-deserialization

在我使用 Retrofit 的 Android 应用程序中,我试图反序列化具有包装项目列表的外部对象的 JSON。我将 GsonConverterFactory 与 Retrofit 实例一起使用来反序列化 JSON。我创建了一个自定义反序列化器以仅从响应中提取项目列表,因此我不必创建父包装类。我以前用 Java 做过这个,但我无法让它与 Kotlin 一起工作。当调用 ItemsService 获取 Items 时,出现以下异常:java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $

我的反序列化器是否有问题,或者我如何使用 Gson 和 Retrofit 配置它?我做错了什么吗?

JSON:

{
    "items" : [
        {
            "id" : "item1"
        },
        {
            "id" : "item2"
        },
        {
            "id" : "item3"
        }
}

反序列化器:

class ItemsDeserializer : JsonDeserializer<List<Item>> {

    override fun deserialize(
        json: JsonElement?,
        typeOfT: Type?,
        context: JsonDeserializationContext?
    ): List<Item> {

        val items: JsonElement = json!!.asJsonObject.get("items")
        val listType= object : TypeToken<List<Item>>() {}.type

        return Gson().fromJson(items, listType)
    }
}

项目:

data class Item (val id: String)

项目服务:

interface ItemsService {

    @GET("items")
    suspend fun getItems(): List<Item>
}

服务工厂:

object ServiceFactory {

    private const val BASE_URL = "https://some.api.com"

    private val gson = GsonBuilder()
        .registerTypeAdapter(object : TypeToken<List<Item>>() {}.type, ItemsDeserializer())
        .create()

    fun retrofit(): Retrofit = Retrofit.Builder()
        .baseUrl(BASE_URL)
        .addConverterFactory(GsonConverterFactory.create(gson))
        .build()

    val itemsService: ItemsService = retrofit().create(ItemsService::class.java)
}

最佳答案

哦,这是一个很常见的错误。您必须使用 TypeToken.getParameterized 创建参数化类型.所以你必须改变object : TypeToken<List<Item>>() {}.typeTypeToken.getParameterized(List::class.java, Item::class.java).type

class ItemsDeserializer : JsonDeserializer<List<Item>> {

    override fun deserialize(
        json: JsonElement?,
        typeOfT: Type?,
        context: JsonDeserializationContext?
    ): List<Item> {

        val items: JsonElement = json!!.asJsonObject.get("items")
        val listType= TypeToken.getParameterized(List::class.java, Item::class.java).type

        return Gson().fromJson(items, listType)
    }
}
private val gson = GsonBuilder()
        .registerTypeAdapter(TypeToken.getParameterized(List::class.java, Item::class.java).type, ItemsDeserializer())
        .create()

关于android - 使用自定义 Gson 反序列化器反序列化 JSON 响应时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61966969/

相关文章:

java - 使用 "canvas = Holder.lockCanvas();"时 Canvas 为空,Android Java

android - 如何修复涉及线程的 Android 内存泄漏?

java - 我的 JSON 输出有什么问题? retrofit.converter.ConversionException 异常

java.lang.IllegalStateException : Expected BEGIN_OBJECT but was STRING at line 1 column 62 错误

android - 当我向 ListView 项目添加 View 时,该项目不再正确 react

java - 如何从 Android 向 PHP 发送 POST 请求

java - 适用于 SRS 传感器的 Android 汽车 CarSensorManager

android - 如何在内部类中定义常量?

kotlin - 为什么每个二级构造函数都需要委托(delegate)给 Kotlin 中的主构造函数?

Android Retrofit 应为 BEGIN_OBJECT 但在第 1 行第 1 列路径 $ 处为 STRING