如何让Room TypeConverter返回正确对象而非LinkedTreeMap?
问题描述
我定义了如下实体类:
@Entity data class ListResponse( @SerializedName("answer") @ColumnInfo(name = "answer") val answer: Map<Int, ItemList> ) data class ItemList( @SerializedName("yes") val yes: YesItem, @SerializedName("no") val no: NoItem ) data class YesItem( @SerializedName("time") val timeYes: String, @SerializedName("date") val dateYes: String ) data class NoItem( @SerializedName("time") val timeNo: String, @SerializedName("date") val dateNo: String )
对应的TypeConverter:
@TypeConverter fun convertFromMapToJSONString(map: Map<Int, ItemList>): String { return Gson().toJson(promotionMap) } @TypeConverter fun convertFromJSONStringToMap(jsonString: String?): Map<Int, ItemList>? { return Gson().fromJson<Map<Int, ItemList>>(jsonString, MutableMap::class.java) }
Repository和Dao代码:
// Repository部分代码 suspend fun insert(respone: ListResponse) { dao.insert(respone) } suspend fun getAll(): ListResponse { return dao.getAll() }
@Dao interface ListDao { @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insert(list: ListResponse): Long @Query("SELECT * FROM $TABLE_NAME") suspend fun getAll(): ListResponse companion object { const val TABLE_NAME = "list_table" } }
目前遇到的问题:liveData.getValue()返回的是LinkedTreeMap而非ListResponse对象,但手动执行以下转换能得到正确的ListResponse:
JsonObject jsonObject = new Gson().toJsonTree(liveData.getValue()).getAsJsonObject(); ListResponse reedUnreadItemList = new Gson().fromJson(jsonObject, ListResponse.class);
想把这个转换逻辑整合到TypeConverter里,让liveData.getValue()直接返回正确的ListResponse对象。
解决方案
问题根源是TypeConverter的反序列化逻辑未指定泛型类型,Gson只能把Map的value解析成默认的LinkedTreeMap,导致整个ListResponse的类型异常。直接修改TypeConverter即可解决:
- 修正序列化方法的笔误
原来的convertFromMapToJSONString里误用了未定义的promotionMap,替换成参数map:
@TypeConverter fun convertFromMapToJSONString(map: Map<Int, ItemList>): String { return Gson().toJson(map) }
- 修改反序列化方法,明确泛型类型
放弃使用MutableMap::class.java,改用TypeToken让Gson识别Map<Int, ItemList>的具体类型:
@TypeConverter fun convertFromJSONStringToMap(jsonString: String?): Map<Int, ItemList>? { val targetType = object : TypeToken<Map<Int, ItemList>>() {}.type return Gson().fromJson(jsonString, targetType) }
- 确认Room关联TypeConverter
在你的RoomDatabase类上加上@TypeConverters注解,引入这个转换器类:
@Database(entities = [ListResponse::class], version = 1) @TypeConverters(YourConverterClass::class) // 替换成你的转换器类名 abstract class AppDatabase : RoomDatabase() { abstract fun listDao(): ListDao }
修改完成后,Room读取数据时会正确解析answer字段的Map结构,liveData.getValue()就能直接返回正确的ListResponse对象,无需再手动转换。
内容的提问来源于stack exchange,提问作者Slava
相关产品推荐
相关产品推荐

