使用自定义的Gson反序列器反序列JSON响应时出错。

问题描述 投票:0回答:1

在使用Retrofit的Android应用程序中,我正试图反序列化JSON,该JSON有一个包裹着项目列表的外部对象。我使用GsonConverterFactory和Retrofit实例来反序列化JSON。我创建了一个自定义的反序列化器,以便只从响应中提取项目列表,这样我就不必创建父包装类。我以前用Java做了这样的工作,但我无法在Kotlin中使用。当调用ItemsService来获取Items时,我得到以下异常。java.lang.IllegalStateException: 期待BEGIN_ARRAY,但在第1行第2列的路径上是BEGIN_OBJECT。

是我的反串器出了问题,还是我在配置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)
    }
}

Item:

data class Item (val id: String)

ItemsService:

interface ItemsService {

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

ServiceFactory:

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)
}
android kotlin gson retrofit2 json-deserialization
1个回答
0
投票

哦,这是一个很常见的错误。你必须在创建参数化类型时使用 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()
© www.soinside.com 2019 - 2024. All rights reserved.