【问题标题】:How to rename the key of a JSON Response dynamically in Retrofit2 Android如何在 Retrofit2 Android 中动态重命名 JSON 响应的键
【发布时间】:2019-11-23 16:40:51
【问题描述】:

我有一个这样的 JSON 响应:

    {
        "AED_BDT": 23.100486
    }

但是如果我的查询是 USD_BDT,那么键会根据我的查询发生变化,那么它会给出这样的响应:

 {
        "USD_BDT": 23.100486
 }

所以,这意味着我需要根据我的查询更改 JSON 键。但我找不到任何关于如何做到这一点的解决方案。

我尝试将响应正文转换为字符串,然后根据我的查询替换密钥,但这不起作用..

这是我的模型类:

data class ResponseCurrencyConvert(
    val USD_BDT: Double
)

这是我迄今为止尝试过的:

val params = HashMap<String,String>()
        params["compact"]="ultra"
        params["apiKey"]= API_KEY
        params["q"]="${currencyFrom}_${currencyTo}"//getting specific currencies and then setting them as query,i.e:USD_BDT
        message(TAG,"Query: ${params["q"]}")
        prefManager.query=params["q"]!!

        //calling the API
        apiServices.convertCurrency(params).enqueue(object : Callback<ResponseCurrencyConvert>{
            override fun onFailure(call: Call<ResponseCurrencyConvert>, t: Throwable) {
                message(TAG,"onFailure: ${t.localizedMessage}")
            }

            override fun onResponse(call: Call<ResponseCurrencyConvert>, response: Response<ResponseCurrencyConvert>) {
               message(TAG,"onResponse Code: ${response.code()}")
               message(TAG,"onResponse Body: ${Gson().toJson(response.body())}")

                val json = Gson().toJson(response.body())//converting the response as string
                val oldValue = "USD_BDT"//the key which was in my model class
                val newValue=params["q"]// the new key which is my query
                val output = json.replace(oldValue,newValue!!,false) // replacing the default query with my query
                val newResponse = Gson().fromJson(output,ResponseCurrencyConvert::class.java)//again converting the new replaced string to json

                    if (response.isSuccessful){

                    message(TAG,"Output: $output")
                    message(TAG,"onResponse Result: ${newResponse?.USD_BDT}")
                    message(TAG,"onResponse newResult: ${newResponse.USD_BDT}")
                    rate= newResponse?.USD_BDT//getting the value; this is returning 0 every time expect when my query is USD_BDT

我评论了我对代码所做的一切,请仔细阅读。非常感谢您的帮助..

【问题讨论】:

  • 将其解析为 HashMap,然后使用 EntrySet 拉取键和值

标签: java android json kotlin retrofit


【解决方案1】:

我猜密钥是从服务器定义的

您可以做的最好的方法是保留两个键并使其可以为空

否则你在 JSON 解析中有一个备用名称

【讨论】:

  • 同意这里,使用2个字段,您可以使用属性或函数获取一个值或另一个检查哪个不为空
  • 简单的方法{ "Currency" : "USD_BDT" "USD_BDT": 23.100486, "AED_BDT": null } 服务器只会告诉你需要解析哪个键,并根据该键只解析那个键
  • 非常感谢您的建议,但这两个仅用作示例,实际上我总共有152种货币,并且每次转换的键都不同,因此很难检查所有这些。
【解决方案2】:

一种方法是维护 2 个不同的键,这是最简单有效的。

实现此目的的另一种方法是将响应类型更改为字符串。当您收到响应时,您更改 JSON 字符串,更改密钥名称,然后使用 GSON 手动从 JSON 转换为 Object。

也许它也可以使用自定义 Json 转换器来完成,但我认为不值得。

【讨论】:

  • 感谢您的建议,我正在尝试这个,但是是否可以使用拦截器更改密钥?因为,通常拦截器用于使用键拦截响应值..我很困惑:(
  • @SoumikBhattacharjee 好吧,也许拦截器不是一个好的解决方案,我已经添加了两个解决方案,请看一下编辑后的回复。
  • 非常感谢您抽出宝贵的时间,我会试试这个,然后告诉您进展如何
  • 是的,最后你的第二个解决方案奏效了,但由于我的响应是一个对象,所以将其类型更改为 String 遇到了一个错误,但按照你的想法,我将响应类型更改为“任何”,然后转换作为字符串的响应并得到了我想要的东西。非常感谢。
【解决方案3】:

如果其他响应的键值发生变化,我建议使用HashMap&lt;String, String&gt;。而不是直接映射到使用 HashMap 动态变化的字符串值会解决您的问题。

告诉我进展如何。

【讨论】:

  • 谢谢你的建议,我一定会让你知道的
猜你喜欢
  • 1970-01-01
  • 2021-09-21
  • 1970-01-01
  • 2021-02-18
  • 2018-08-16
  • 1970-01-01
  • 1970-01-01
  • 2020-04-01
  • 1970-01-01
相关资源
最近更新 更多