David Raja
David Raja

Reputation: 51

Android ROOM save Map<String, Object>

I have a model like that

@Entity(tableName = "allrates")
class Data(
        @ColumnInfo(name = "rates")
        @SerializedName("rates")
        @Expose
        var rates: Map<String, Rates>,

        @ColumnInfo(name = "start")
        @SerializedName("start_at")
        @Expose
        var startDate: String,

        @ColumnInfo(name = "end")
        @SerializedName("end_at")
        @Expose
        var endDate: String,

        @SerializedName("base")
        @Expose
        var base: String,

        @PrimaryKey(autoGenerate = true)
        var id: Int  
)

And my problem is when I trying to insert in the database, doesn't show me any error but when I do the ´get´ is always returning me a null. So probably, my problem is in the ´Converter´ but I not sure about that.

And this is my converter

class mapConverter {
    @TypeConverter
    fun fromString(value: String): Map<String, Rates> {
        val mapType = object : TypeToken<Map<String, Rates>>() {

        }.type
        return Gson().fromJson(value, mapType)
    }

    @TypeConverter
    fun fromStringMap(map: Map<String, Rates>): String {
        val gson = Gson()
        return gson.toJson(map)
    }
}

And here goes the DAO

@Dao
abstract class RatesDao {

    @Query("SELECT * FROM allrates")
    abstract fun loadRates(): LiveData<Data>

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    abstract fun insertRates(rates: Data)
}

Connexion with ROOM

@Database(entities = [(Data::class)], version = 1, exportSchema = false)
@TypeConverters(mapConverter::class)
abstract class AppDatabase : RoomDatabase() {

    companion object {
        private var sInstance: AppDatabase? = null
        private const val DATABASE_NAME: String = "RatesList"

        fun getInstance(context: Context): AppDatabase {
            if (sInstance == null) {
                synchronized(AppDatabase::class) {
                    sInstance = Room.databaseBuilder(context.applicationContext,
                            AppDatabase::class.java, DATABASE_NAME)
                            .build()
                }
            }
            return sInstance as AppDatabase
        }
    }

    abstract fun ratesDao(): RatesDao
}

Upvotes: 5

Views: 9312

Answers (2)

Mert
Mert

Reputation: 1005

Write a converter to Rates too, paste below code to your converter class:

    @TypeConverter
    fun fromStringMap(map: Map<String, Rates>): String {
        return Gson().toJson(fromStringMap)
    }

    @TypeConverter
    fun fromString(value: String): Map<String, Rates> {
        return Gson().fromJson(value, object : TypeToken<Map<String, Rates>>() {}.type)
    }

    @TypeConverter
    fun fromArea(rates: Rates): String {
        return Gson().toJson(rates)
    }

    @TypeConverter
    fun toArea(ratesString: String): Rates {
        return Gson().fromJson(ratesString, object : TypeToken<Rates>() {}.type)
    }

Don't forget to serialize to your Rates data class:

import java.io.Serializable

data class Rates(
    // your code
): Serializable

Upvotes: 0

Ivan Vovk
Ivan Vovk

Reputation: 1039

You are writing your code in Kotlin, so add this line @JvmStatic to MapConverter class as follows:

class  MapConverter {
    companion object{
        @JvmStatic
        @TypeConverter
        fun fromString(value: String): Map<String, String> {
            val mapType = object : TypeToken<Map<String, String>>() {}.type
            return Gson().fromJson(value, mapType)
        }
        @TypeConverter
        @JvmStatic
        fun fromStringMap(map: Map<String, String>): String {
            val gson = Gson()
            return gson.toJson(map)
        }
    }
}

Upvotes: 1

Related Questions