I have a Plant data class, that has a PlantType sealed class parameter. I am using a Room local db, but when I try to parse it it fails. It works for other classes that has initializable class parameters.
Thanks for the help in advance.
The error:
java.lang.RuntimeException: Failed to invoke private com.tenyitamas.mylittlegarden.domain.util.PlantType() with no args
at com.tenyitamas.mylittlegarden.data.util.Converters.fromPlantsJson(Converters.kt:99)
// Comment: Converters.kt: 99 is the from json part of the Converters code, I included.
Plant.kt:
data class Plant(
val type: PlantType,
val upgrades: Upgrades
)
PlantType.kt:
sealed class PlantType {
object Carrot : PlantType()
object Tomato : PlantType()
object Cucumber : PlantType()
object Lettuce : PlantType()
object Strawberry : PlantType()
private companion object Constants {
const val INITIAL_TIME_CARROT = 5_000L // 5s
const val INITIAL_TIME_TOMATO = 6_000L
const val INITIAL_TIME_CUCUMBER = 7_000L
const val INITIAL_TIME_LETTUCE = 8_000L
const val INITIAL_TIME_STRAWBERRY = 9_000L
const val INITIAL_COST_CARROT = 10
const val INITIAL_COST_TOMATO = 100
const val INITIAL_COST_CUCUMBER = 1_000
const val INITIAL_COST_LETTUCE = 10_000
const val INITIAL_COST_STRAWBERRY = 100_000
const val INITIAL_INCOME_CARROT = 10
const val INITIAL_INCOME_TOMATO = 100
const val INITIAL_INCOME_CUCUMBER = 1_000
const val INITIAL_INCOME_LETTUCE = 10_000
const val INITIAL_INCOME_STRAWBERRY = 100_000
}
val name: String
get() {
return when (this) {
Carrot -> Resources.getSystem().getString(R.string.carrot)
Tomato -> Resources.getSystem().getString(R.string.tomato)
Cucumber -> Resources.getSystem().getString(R.string.cucumber)
Lettuce -> Resources.getSystem().getString(R.string.lettuce)
Strawberry -> Resources.getSystem().getString(R.string.strawberry)
}
}
val image: Bitmap
get() {
return when (this) {
Carrot -> {
BitmapFactory.decodeResource(Resources.getSystem(), R.drawable.ic_carrot)
}
Tomato -> {
BitmapFactory.decodeResource(Resources.getSystem(), R.drawable.ic_tomato)
}
Cucumber -> {
BitmapFactory.decodeResource(Resources.getSystem(), R.drawable.ic_cucumber)
}
Lettuce -> {
BitmapFactory.decodeResource(Resources.getSystem(), R.drawable.ic_lettuce)
}
Strawberry -> {
BitmapFactory.decodeResource(Resources.getSystem(), R.drawable.ic_strawberry)
}
}
}
val initialTime: Long
get() {
return when (this) {
Carrot -> INITIAL_TIME_CARROT
Tomato -> INITIAL_TIME_TOMATO
Cucumber -> INITIAL_TIME_CUCUMBER
Lettuce -> INITIAL_TIME_LETTUCE
Strawberry -> INITIAL_TIME_STRAWBERRY
}
}
val initialCost: Int
get() {
return when (this) {
Carrot -> INITIAL_COST_CARROT
Tomato -> INITIAL_COST_TOMATO
Cucumber -> INITIAL_COST_CUCUMBER
Lettuce -> INITIAL_COST_LETTUCE
Strawberry -> INITIAL_COST_STRAWBERRY
}
}
val initialIncome: Int
get() {
return when (this) {
Carrot -> INITIAL_INCOME_CARROT
Tomato -> INITIAL_INCOME_TOMATO
Cucumber -> INITIAL_INCOME_CUCUMBER
Lettuce -> INITIAL_INCOME_LETTUCE
Strawberry -> INITIAL_INCOME_STRAWBERRY
}
}
}
Converters.kt
@TypeConverter
fun fromPlantsJson(json: String): List<Plant> {
return jsonParser.fromJson<ArrayList<Plant>>(
json,
object : TypeToken<ArrayList<Plant>>(){}.type
) ?: emptyList()
}
@TypeConverter
fun toPlantsJson(plants: List<Plant>): String {
return jsonParser.toJson(
plants,
object : TypeToken<ArrayList<Plant>>(){}.type
) ?: "[]"
}
CodePudding user response:
Your PlantType sealed class has only objects inside it. You can just use an enum for this.
enum class PlantType {
Carrot, Tomato, Cucumber, Lettuce, Strawberry
}
And most likely your jsonParser will be able to serialize this enum.
Edit: In your edited question, you just have added some new vals inside the PlantType class all of which has custom getters which return value depending upon the PlantType. You can still replace it with the enum and put those vals as extensions on PlantType.
For example,
enum class PlantType {
Carrot, Tomato, Cucumber, Lettuce, Strawberry
}
val PlantType.name: String
get() {
return when (this) {
Carrot -> Resources.getSystem().getString(R.string.carrot)
Tomato -> Resources.getSystem().getString(R.string.tomato)
Cucumber -> Resources.getSystem().getString(R.string.cucumber)
Lettuce -> Resources.getSystem().getString(R.string.lettuce)
Strawberry -> Resources.getSystem().getString(R.string.strawberry)
}
}
