androidkotlinandroid-room

Why does the Converter for Room not work?


I encountered this error:

Cannot figure out how to save this field into database. You can consider adding a type converter for it.
    private final java.util.List<com.example.dictionary.dictionary.domain.model.ExampleModel> Example = null;

As I understand it, this error appears when you use a list in the Room model:

@Entity
data class WordInfoEntity(
    @PrimaryKey val id:Int?=null,
    val Word:String,
    val Translation:String,
    val Example:List<ExampleModel>,
) {
    fun toWordModel(): WordModel{
        return WordModel(
            id=id!!,
            Word=Word,
            Translation=Translation,
            Example=Example,
        )
    }
}

But I have a converter that should convert the model:

interface JsonParser {
    fun <T> fromJson(json: String, type: Type): T?

    fun <T> toJson(obj: T, type: Type): String?
}

class GsonParser(
    private val gson: Gson,
) : JsonParser {
    override fun <T> fromJson(json: String, type: Type): T? =
        gson.fromJson(json, type)

    override fun <T> toJson(obj: T, type: Type): String? =
        gson.toJson(obj, type)
}

@ProvidedTypeConverter
class Converters(
    private val jsonParser: JsonParser,
) {
    @TypeConverter
    fun fromWordsJson(json: String): List<WordModel> =
        jsonParser.fromJson<ArrayList<WordModel>>(
            json,
            object : TypeToken<ArrayList<WordModel>>() {}.type,
        ) ?: emptyList()

    @TypeConverter
    fun toWordsJson(word: List<WordModel>): String =
        jsonParser.toJson(
            word,
            object : TypeToken<ArrayList<WordModel>>() {}.type,
        ) ?: "[]"
}

Here I use the converter:

@Database(
    entities = [WordInfoEntity::class],
    version = 1,
)

@TypeConverters(Converters::class)
abstract class WordInfoDataBase : RoomDatabase() {
    abstract val dao: WordInfoDao
}

And

@Provides
@Singleton
fun provideWordInfoDatabase(app:Application):WordInfoDataBase{
    return Room.databaseBuilder(
        app, WordInfoDataBase::class.java, "word_db"
    ).addTypeConverter(Converters(GsonParser(Gson())))
        .build()
}

And at the same moment, the functions are not highlighted as used:

I do not understand why the functions from the converter do not want to be used, provided that I have linked them.


Solution

  • Since your data class which is also a Room Column contains List<ExampleModel>, you need to make sure Room is able to convert it properly to store it. This is pretty clear from the warning as well

    data class WordInfoEntity(
        @PrimaryKey val id:Int?=null,
        val Word:String,
        val Translation:String,
        val Example:List<ExampleModel>,  // Need to write type converter for this and not WordModel
    ) {
        fun toWordModel(): WordModel{
            return WordModel(
                id=id!!,
                Word=Word,
                Translation=Translation,
                Example=Example,
            )
        }
    }
    

    Maybe you can turn your existing type converters like so. Converted all usages of WordModel to ExampleModel

    @ProvidedTypeConverter
    class Converters(
        private val jsonParser: JsonParser,
    ) {
        @TypeConverter
        fun fromWordsJson(json: String): List<ExampleModel> =
            jsonParser.fromJson<ArrayList<ExampleModel>>(
                json,
                object : TypeToken<ArrayList<ExampleModel>>() {}.type,
            ) ?: emptyList()
    
        @TypeConverter
        fun toWordsJson(word: List<ExampleModel>): String =
            jsonParser.toJson(
                word,
                object : TypeToken<ArrayList<ExampleModel>>() {}.type,
            ) ?: "[]"
    }