如何使用Gson和Retrofit将类似的Json对象转换为Json数组

djp7away  于 2022-11-06  发布在  其他
关注(0)|答案(1)|浏览(210)

假设我从API得到的响应低于

{"success":true,
"base":"EUR",
"date":"2021-04-16",
"rates":
{"AED":4.393943,"AFN":92.83145,"ALL":123.125765,"AMD":621.059723}}

我希望最后一个rates对象是一个List of Rate类,即Rate(code=“AED”,value=“4.393943”)。我正在使用Retrofit和Gson。我知道我需要一个反序列化器或类型适配器。我只是不知道如何编写一个。
费率分类:

data class Rate(
    val code:String,
    val value:Float
)

货币分类:

data class Currency(
    @SerializedName("success")
    val success: Boolean?,
    @SerializedName("base")
    val base: String?,
    @SerializedName("date")
    val date: Date?,
    @SerializedName("rates")
    val rates: List<Rate>?
)

这是请求:

val gson: Gson = GsonBuilder()
    .registerTypeHierarchyAdapter(Rate::class.java, TypeAdapterOrDeserializer())
    .create()
val retrofit = Retrofit.Builder()
    .baseUrl("https://api.exchangerate.host")
    .addConverterFactory(GsonConverterFactory.create(gson))
    .build()
val jsonPlaceholderApi = retrofit.create(JsonPlaceholderApi::class.java)
val call = jsonPlaceholderApi.currency

当我从api请求数据时,它给出了这个错误,我知道为什么;),因为我已经给出了货币类中的汇率列表,但它是一个json汇率对象。java.lang.IllegalStateException:应为开始_ARRAY,但实际为BEGIN_OBJECT
谢谢你的帮助:)

y4ekin9u

y4ekin9u1#

API返回的rates的数据是一个JSON对象,但在数据类中,您将其定义为List,因此Gson期望它是一个JSON数组。在这种情况下,您需要为Currency类自定义解析。
使用此反序列化程序:

class CurrencyDeserializer : JsonDeserializer<Currency> {
    override fun deserialize(json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?): Currency {
        if (json == null || context == null) {
            // handle error here
            throw Exception("Error")
        }
        val obj = json.asJsonObject

        // let Gson handle the other 3 properties
        val success = context.deserialize<Boolean?>(obj.get("success"), Boolean::class.java)
        val base = context.deserialize<String?>(obj.get("base"), String::class.java)
        val date = context.deserialize<Date?>(obj.get("date"), Date::class.java)

        // create List<Rate> from the rates JsonObject
        val ratesSet = obj.get("rates").asJsonObject.entrySet()
        val ratesList = ratesSet.map {
            val code = it.key
            val value = it.value.asFloat
            Rate(code, value)
        }

        return Currency(success, base, date, ratesList)
    }
}

将其添加到Gson,如下所示:

val gson: Gson = GsonBuilder()
    .registerTypeAdapter(Currency::class.java, CurrencyDeserializer())
    .create()

相关问题