Android Room嵌套JSON存储报错:需添加类型转换器解决字段存储问题
解决Android Room存储嵌套JSON数据的报错问题
报错Cannot figure out how to save this field into database. You can consider adding a type converter for it的核心原因是:Room默认只支持存储基本数据类型(String、Int、Boolean等)或标记为@Entity的实体类,而你代码中的title、content是自定义嵌套对象,Room无法直接识别和存储它们。
解决方法是通过TypeConverter(类型转换器),将嵌套对象与数据库支持的String类型互相转换(把对象序列化为JSON字符串存储,读取时再反序列化为对象)。
步骤1:添加Gson依赖(若未添加)
在模块级build.gradle的dependencies中添加Gson依赖,用于JSON序列化/反序列化:
implementation 'com.google.code.gson:gson:2.10.1'
步骤2:创建TypeConverter类
新建类实现嵌套对象与String的互转逻辑:
import com.google.gson.Gson import com.google.gson.reflect.TypeToken class Converters { private val gson = Gson() // 将Title对象转为String @androidx.room.TypeConverter fun titleToString(title: Title?): String? { return title?.let { gson.toJson(it) } } // 将String转为Title对象 @androidx.room.TypeConverter fun stringToTitle(json: String?): Title? { val type = object : TypeToken<Title>() {}.type return json?.let { gson.fromJson(it, type) } } // 将Content对象转为String @androidx.room.TypeConverter fun contentToString(content: Content?): String? { return content?.let { gson.toJson(it) } } // 将String转为Content对象 @androidx.room.TypeConverter fun stringToContent(json: String?): Content? { val type = object : TypeToken<Content>() {}.type return json?.let { gson.fromJson(it, type) } } }
步骤3:修正实体类问题
title、content不是Room实体,无需@PrimaryKey和@ColumnInfo注解,同时调整类名首字母大写(符合Kotlin命名规范):
@Entity(tableName = "icerik") data class Icerik( @ColumnInfo(name = "title") @SerializedName("title") val baslik: Title?, @ColumnInfo(name = "content") @SerializedName("content") val icerik: Content?, @ColumnInfo(name = "date") @SerializedName("date") val tarih: String?, @ColumnInfo(name = "jetpack_featured_media_url") @SerializedName("jetpack_featured_media_url") val gorsel: String? ) { @PrimaryKey(autoGenerate = true) var uuid: Int = 0 } data class Content( @SerializedName("rendered") val content: String?, @SerializedName("protected") val bool: Boolean? ) data class Title( @SerializedName("rendered") val ytitle: String? )
步骤4:在Database类中注册TypeConverter
在IcerikDatabase类上添加@TypeConverters注解,让Room识别转换器:
@Database(entities = [Icerik::class], version = 1) @TypeConverters(Converters::class) // 注册转换器 abstract class IcerikDatabase : RoomDatabase() { abstract fun icerikDao(): IcerikDAO companion object { @Volatile private var instance: IcerikDatabase? = null private val lock = Any() operator fun invoke(context: Context) = instance ?: synchronized(lock) { instance ?: databaseOlustur(context).also { instance = it } } private fun databaseOlustur(context: Context) = Room.databaseBuilder( context.applicationContext, IcerikDatabase::class.java, "icerikdatabase" ).build() } }
验证逻辑
完成修改后,Room会自动在存储Icerik对象时,将baslik(Title类型)和icerik(Content类型)转为JSON字符串存入数据库;读取时再自动转换为对应对象,即可解决报错并实现嵌套JSON的存储。
内容的提问来源于stack exchange,提问作者Kerim Berkay
相关产品推荐
相关产品推荐

