如何使用Room创建以Map的Int键为主键的@Entity实体类
完善Room实体类以适配Map键作为主键的需求
问题背景
现有网络请求返回的数据类结构如下:
data class ListResponse( @SerializedName("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 )
需要创建Room数据库,表结构要求:以ListResponse.answer中Map的Int键作为主键(对应字段id),同时包含timeYes、dateYes、timeNo、dateNo四个字段。现有不完整的实体类,需完成其实现。
完善后的Room实体类
@Entity(tableName = TABLE_NAME) data class PromotionListEntity( @PrimaryKey val id: Int, // Map的Int键直接作为主键,无需@SerializedName(原JSON无对应字段) @SerializedName("timeYes") val timeYes: String, @SerializedName("dateYes") val dateYes: String, @SerializedName("timeNo") val timeNo: String, @SerializedName("dateNo") val dateNo: String ) { companion object { const val TABLE_NAME = "answer_table" } }
关键说明
- 主键
id的处理:原JSON中answer是一个动态键的对象,Gson将其解析为Map<Int, ItemList>,这个Int键并不是某个JSON字段的取值,而是对象的key,因此实体类中的id无需添加@SerializedName注解,在从原数据类转换为实体类时,直接将Map的key赋值给id即可。 - 字段注解说明:
timeYes、dateYes等字段的@SerializedName是为了在需要将实体类转换回JSON时保持字段名对应,如果仅用于Room存储,其实可以省略这些注解(Room不依赖@SerializedName,只看字段名)。
数据转换示例
如果需要将ListResponse中的数据转换为可插入Room的实体类列表,可添加如下扩展函数:
fun ListResponse.toPromotionEntities(): List<PromotionListEntity> { return answer.map { (mapKey, itemList) -> PromotionListEntity( id = mapKey, timeYes = itemList.yes.timeYes, dateYes = itemList.yes.dateYes, timeNo = itemList.no.timeNo, dateNo = itemList.no.dateNo ) } }
内容的提问来源于stack exchange,提问作者Slava
相关产品推荐
相关产品推荐

