【问题标题】:How to convert similar Json objects to Json Arrays with Gson and Retrofit如何使用 Gson 和 Retrofit 将类似的 Json 对象转换为 Json 数组
【发布时间】:2021-07-11 02:58:48
【问题描述】:

假设我收到来自 API 的以下响应

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

并且我希望最后一个费率对象是费率类列表,即费率(代码 =“AED”,值 =“4.393943”)。我正在使用改造和 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 请求数据时,它给出了这个错误,我知道为什么;)因为我在 Currency 类中给出了汇率列表,但它是一个 json 汇率对象。 com.google.gson.JsonSyntaxException:java.lang.IllegalStateException:应为 BEGIN_ARRAY,但为 BEGIN_OBJECT

感谢您的帮助:)

【问题讨论】:

    标签: android json kotlin gson retrofit


    【解决方案1】:

    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()
    

    【讨论】:

    • @PrathameshMore 在这种情况下请将其标记为答案,以便它也可以帮助其他人。
    猜你喜欢
    • 2016-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-19
    • 2016-08-07
    • 2021-06-18
    • 2017-06-11
    • 1970-01-01
    相关资源
    最近更新 更多