【问题标题】:Error deserializing JSON response with custom Gson deserializer使用自定义 Gson 反序列化器反序列化 JSON 响应时出错
【发布时间】:2020-09-09 23:59:10
【问题描述】:

在我使用 Retrofit 的 Android 应用程序中,我试图反序列化具有包含项目列表的外部对象的 JSON。我正在使用带有 Retrofit 实例的 GsonConverterFactory 来反序列化 JSON。我创建了一个自定义反序列化器来仅从响应中提取项目列表,因此我不必创建父包装类。我以前用 Java 做过这个,但我不能让它和 Kotlin 一起工作。当调用 ItemsService 到 getItems 时,我收到以下异常: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)
}

【问题讨论】:

    标签: android kotlin gson retrofit2 json-deserialization


    【解决方案1】:

    哦,这是一个很常见的错误。您必须使用TypeToken.getParameterized 创建参数化类型。所以你必须把object : TypeToken&lt;List&lt;Item&gt;&gt;() {}.type改成TypeToken.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()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-09
      • 2013-09-09
      • 1970-01-01
      相关资源
      最近更新 更多