如何为动态key的JSON创建适配Retrofit与Jetpack的Data Class
问题原因
你当前的类定义存在不必要的层级封装,这是解析失败的核心原因:
接口返回的data字段本身就是以货币代码为键、汇率为值的JSON对象,而你额外定义的Data类要求Gson在data对象下查找名为hashmapForData的子字段,实际返回结果中不存在该字段,因此解析失败。
正确实现方案
无需单独定义Data类,直接将响应类中的data字段声明为Map类型即可:
// 根响应类 data class CurrencyResponse( val query: Query, val data: Map<String, Double> ) // Query字段对应类 data class Query( val apikey: String, val base_currency: String, val timestamp: Long // 建议改为Long类型,避免2038年Int溢出问题 )
数值类型说明
即使部分汇率值为整数格式(如示例中的LTC: 0),Gson也可以正常将其解析为Double类型;如果对汇率精度要求极高,可将Map的值类型改为BigDecimal避免浮点精度丢失。
配合Android Jetpack组件的常用实践
1. 列表展示适配
如果需要在RecyclerView中展示汇率列表,可将Map<String, Double>转换为实体类列表,配合ListAdapter使用:
data class CurrencyRate( val code: String, val rate: Double ) // 转换示例 val rateList = currencyResponse.data.map { CurrencyRate(it.key, it.value) }
2. Room持久化适配
如果需要用Room存储响应结果,可添加类型转换器实现Map的持久化:
import androidx.room.TypeConverter import com.google.gson.Gson import com.google.gson.reflect.TypeToken class RateConverters { @TypeConverter fun mapToJson(map: Map<String, Double>): String { return Gson().toJson(map) } @TypeConverter fun jsonToMap(json: String): Map<String, Double> { val type = object : TypeToken<Map<String, Double>>() {}.type return Gson().fromJson(json, type) } }
在Room Database类上添加注解即可生效:
@Database(entities = [YourEntity::class], version = 1) @TypeConverters(RateConverters::class) abstract class AppDatabase : RoomDatabase() { // 数据库操作Dao定义 }
3. 架构适配
可将Retrofit请求结果包装为Flow或LiveData返回,配合ViewModel实现生命周期感知,符合Jetpack架构规范。
内容的提问来源于stack exchange,提问作者commandiron
相关产品推荐
相关产品推荐

