在 Kotlin 中使用自定义 JsonDeserializer 进行改造

Posted

技术标签:

【中文标题】在 Kotlin 中使用自定义 JsonDeserializer 进行改造【英文标题】:Retrofit with custom JsonDeserializer in Kotlin 【发布时间】:2020-09-08 06:15:24 【问题描述】:

我需要解析这个 json。默认情况下它工作正常,但我需要添加时间戳,所以我使用自定义反序列化工厂。

[
  
"ccy": "USD",
"base_ccy": "UAH",
"buy": "26.60000",
"sale": "26.96000"
  ,
  
"ccy": "EUR",
"base_ccy": "UAH",
"buy": "28.95000",
"sale": "29.60000"
  ,
  
"ccy": "RUR",
"base_ccy": "UAH",
"buy": "0.35000",
"sale": "0.38500"
  ,
  
"ccy": "BTC",
"base_ccy": "USD",
"buy": "8610.8989",
"sale": "9517.3093"
 
]

但是 json: JsonElement? MyDeserializer 中的参数从不与 ArrayList 一起提供,总是在单个对象中。我如何读取 ArrayList 的远程 json 并对其进行修改?

 class MyDeserializer : JsonDeserializer<ArrayList<CurrencyItem>> 

    override fun deserialize(
        json: JsonElement?,
        typeOfT: Type?,
        context: JsonDeserializationContext?
    ): ArrayList<CurrencyItem> 

        //Clean array save result
        var currrencyList = ArrayList<CurrencyItem>()

        // Get remote json
        val itemsJsonArray = jsonObject.asJsonArray

       //Modify remote json to custom object with timestamp
        for (item in itemsJsonArray) 

            var JsonObject = item.asJsonObject

            var ccy = JsonObject.get("ccy").asString
            var base_ccy = JsonObject.get("base_ccy").asString
            var buy = JsonObject.get("buy").asString
            var sale = JsonObject.get("sale").asString

            var timestamp = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())

            currrencyList.add(CurrencyItem(1, ccy, base_ccy, buy, sale, time))

        
        return currrencyList
    



添加自定义转换器进行改造

       //Add converter to retrofit
        val retrofit =
        Retrofit.Builder().baseUrl("https://api.privatbank.ua/")

            //My custom converter
            .addConverterFactory(GsonConverterFactory.create(customGson))

           .client(okkHttpclient)
           .build()

【问题讨论】:

您是否将您的反序列化器作为您的类型 (ArrayList) 的适配器添加到 gsonBuilder ?如果你不告诉它,Retrofit 不会神奇地知道它需要使用它。 我只添加了工厂 .addConverterFactory(GsonConverterFactory.create(customGson)) “customGson”是如何创建的? //自定义 JSON val customGson = GsonBuilder().registerTypeAdapter(CurrencyItem::class.java, MyDeserializer()).create() 好吧,问题来了,我给它写一个正确的答案 【参考方案1】:

问题是你用错误的类型注册你的反序列化器:

JsonDeserializer<ArrayList<CurrencyItem>>

你的反序列化器的类型是

ArrayList<CurrentItem>

然而,你正在注册它

CurrencyItem::class.java

现在,注册泛型类型不像普通类型那样简单。 在您的情况下,您需要:

Type currencyItemListType = new TypeToken<ArrayList<CurrencyItem>>() .getType();
registerTypeAdapter(currencyItemListType, MyDeserializer())code here

这样,当 de retrofit 调用返回成功代码 (2xx) 时,它应该自动尝试使用您的反序列化器反序列化 json

【讨论】:

如果我注册 val currencyItemListType = object : TypeToken?>() .type // val customGson = GsonBuilder().registerTypeAdapter(currencyItemListType, MyDeserializer()).create () // JsonDeserializer 像 > 一样工作

以上是关于在 Kotlin 中使用自定义 JsonDeserializer 进行改造的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Kotlin 创建自定义视图的构造函数

Kotlin自定义注释,参数

Android 使用Kotlin来实现自定义View之雷达图

Android 使用Kotlin来实现自定义View之雷达图

Android 使用Kotlin来实现自定义View之雷达图

Android 使用Kotlin来实现自定义View之雷达图