Persistente bibliotheek van Android-kamer – TypeConverter-fout van fout: kan niet achterhalen hoe veld in database moet worden opgeslagen”

Ik kan door een fout geen typeConverter in de kamer maken. Ik schijn alles te volgen volgens de documenten. Ik wil graag een lijst converteren naar een json-string. laten we eens kijken naar mijn entiteit:

     @Entity(tableName = TABLE_NAME)
public class CountryModel {
    public static final String TABLE_NAME = "Countries";
    @PrimaryKey
    private int idCountry;
/* I WANT TO CONVERT THIS LIST TO A JSON STRING */
    private List<CountryLang> countryLang = null;
    public int getIdCountry() {
        return idCountry;
    }
    public void setIdCountry(int idCountry) {
        this.idCountry = idCountry;
    }
    public String getIsoCode() {
        return isoCode;
    }
    public void setIsoCode(String isoCode) {
        this.isoCode = isoCode;
    }
    public List<CountryLang> getCountryLang() {
        return countryLang;
    }
    public void setCountryLang(List<CountryLang> countryLang) {
        this.countryLang = countryLang;
    }
}

De country_langis wat ik zou willen converteren naar een string-json. Dus ik heb de volgende converter gemaakt:
Converters.java:

public class Converters {
@TypeConverter
public static String countryLangToJson(List<CountryLang> list) {
    if(list == null)
        return null;
        CountryLang lang = list.get(0);
    return list.isEmpty() ? null : new Gson().toJson(lang);
}}

dan is het probleem overal waar ik de @TypeConverters({Converters.class}) plaats, ik krijg steeds een foutmelding. Maar officieel heb ik hier de annotatie geplaatst om de typeConverter geregistreerd te krijgen:

@Database(entities = {CountryModel.class}, version = 1 ,exportSchema = false)
@TypeConverters({Converters.class})
public abstract class MYDatabase extends RoomDatabase {
    public abstract CountriesDao countriesDao();
}

De fout die ik krijg is:

Error:(58, 31) error: Cannot figure out how to save this field into database. You can consider adding a type converter for it.

Antwoord 1, autoriteit 100%

Dit is een veelvoorkomend probleem dat ik heb gezien sinds Room werd aangekondigd. Room ondersteunt niet de mogelijkheid om lijsten rechtstreeks op te slaan, noch de mogelijkheid om naar/van lijsten te converteren. Het ondersteunt het converteren en opslaan van POJO’s.

In dit geval is de oplossing eenvoudig. In plaats van een List<CountryLang>op te slaan, wil je CountryLangsopslaan (let op de ‘s’)

Ik heb hier een snel voorbeeld van een oplossing gegeven:

public class CountryLangs {
    private List<String> countryLangs;
    public CountryLangs(List<String> countryLangs) {
        this.countryLangs = countryLangs;
    }
    public List<String> getCountryLangs() {
        return countryLangs;
    }
    public void setCountryLangs(List<String> countryLangs) {
        this.countryLangs = countryLangs;
    }
}

Deze POJO is een inversie van je vorige object. Het is een object dat een lijst met talen opslaat. In plaats van een lijst met objecten die uw taal opslaan.

public class LanguageConverter {
    @TypeConverter
    public CountryLangs storedStringToLanguages(String value) {
        List<String> langs = Arrays.asList(value.split("\\s*,\\s*"));
        return new CountryLangs(langs);
    }
    @TypeConverter
    public String languagesToStoredString(CountryLangs cl) {
        String value = "";
        for (String lang :cl.getCountryLangs())
            value += lang + ",";
        return value;
    }
}

Deze converter neemt een lijst met strings en converteert deze naar een door komma’s gescheiden string die in een enkele kolom moet worden opgeslagen. Wanneer het de string uit de SQLite db haalt om terug te converteren, splitst het de lijst op komma’s en vult het de CountryLangs.

Zorg ervoor dat u uw RoomDatabase-versie bijwerkt nadat u deze wijzigingen heeft aangebracht. De rest van de configuratie is correct. Veel plezier met jagen met de rest van je Room-persistentiewerk.


Antwoord 2, autoriteit 74%

Dezelfde fout: “Kan niet achterhalen hoe dit veld in de database moet worden opgeslagen” tijdens het toevoegen van een datumveld. Moest er een conversieklasse voor toevoegen en @TypeConverters-annotatie aan het veld toevoegen.

Voorbeeld:

WordEntity.java

import androidx.room.TypeConverters;
@Entity
public class WordEntity {
    @PrimaryKey(autoGenerate = true)
    public int id;
    private String name;
    @TypeConverters(DateConverter.class)
    private Date createDate;
    ...
}

DateConverter.java:

import androidx.room.TypeConverter;    
import java.util.Date;
public class DateConverter {
    @TypeConverter
    public static Date toDate(Long timestamp) {
        return timestamp == null ? null : new Date(timestamp);
    }
    @TypeConverter
    public static Long toTimestamp(Date date) {
        return date == null ? null : date.getTime();
    }
}

Antwoord 3, autoriteit 26%

Ik heb de typeconverters gebruikt die hier worden beschreven (artikel op Medium .com)en het werkte:

@TypeConverter
    public static List<MyObject> storedStringToMyObjects(String data) {
        Gson gson = new Gson();
        if (data == null) {
            return Collections.emptyList();
        }
        Type listType = new TypeToken<List<MyObject>>() {}.getType();
        return gson.fromJson(data, listType);
    }
    @TypeConverter
    public static String myObjectsToStoredString(List<MyObject> myObjects) {
        Gson gson = new Gson();
        return gson.toJson(myObjects);
    }

Antwoord 4, autoriteit 12%

Voor het geval je meer duidelijkheid nodig hebt.

Maak eerst een algemene conversieklasse zoals hieronder.

class Converters {
@TypeConverter
fun fromGroupTaskMemberList(value: List<Comment>): String {
    val gson = Gson()
    val type = object : TypeToken<List<Comment>>() {}.type
    return gson.toJson(value, type)
}
@TypeConverter
fun toGroupTaskMemberList(value: String): List<Comment> {
    val gson = Gson()
    val type = object : TypeToken<List<Comment>>() {}.type
    return gson.fromJson(value, type)
}

}

Voeg deze converter vervolgens toe aan de databaseklasse, net als,

@TypeConverters(Converters::class)

abstracte klasse AppDatabase : RoomDatabase() {


Antwoord 5, autoriteit 9%

@TypeConverterherkent de klasse Listniet, dus u moet in plaats daarvan ArrayListgebruiken, zodat u geen extra wrapper voor de lijst die u wilt behouden.


Antwoord 6, autoriteit 9%

annoteer dat object gewoon met @Embedded loste mijn probleem op. Vind dit leuk

@Embedded
private List<CrewListBean> crewList;

Antwoord 7, autoriteit 9%

Misschien ben ik te laat om te antwoorden, maar ik heb hier een eenvoudige oplossing voor. Ik deel de TypeConverters-oproep die een aantal basisvereisten afhandelt

class RoomConverters {
//for date and time convertions
@TypeConverter
fun calendarToDateStamp(calendar: Calendar): Long = calendar.timeInMillis
@TypeConverter
fun dateStampToCalendar(value: Long): Calendar =
    Calendar.getInstance().apply { timeInMillis = value }
//list of cutome object in your database
@TypeConverter
fun saveAddressList(listOfString: List<AddressDTO?>?): String? {
    return Gson().toJson(listOfString)
}
@TypeConverter
fun getAddressList(listOfString: String?): List<AddressDTO?>? {
    return Gson().fromJson(
        listOfString,
        object : TypeToken<List<String?>?>() {}.type
    )
}
/*  for converting List<Double?>?  you can do same with other data type*/
@TypeConverter
fun saveDoubleList(listOfString: List<Double>): String? {
    return Gson().toJson(listOfString)
}
@TypeConverter
fun getDoubleList(listOfString: List<Double>): List<Double> {
    return Gson().fromJson(
        listOfString.toString(),
        object : TypeToken<List<Double?>?>() {}.type
    )
}
// for converting the json object or String into Pojo or DTO class
@TypeConverter
fun toCurrentLocationDTO(value: String?): CurrentLocationDTO {
    return  Gson().fromJson(
        value,
        object : TypeToken<CurrentLocationDTO?>() {}.type
    )
}
@TypeConverter
fun fromCurrentLocationDTO(categories: CurrentLocationDTO?): String {
    return Gson().toJson(categories)
}
}

je moet eigen klassen schrijven en hier ontleden en daarna toevoegen aan je AppDatabase-klasse

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

Antwoord 8, autoriteit 7%

Kotlin-voorbeeld (niet goed maar eenvoudig, TODO: json):

import android.arch.persistence.room.*
@Entity(tableName = "doctor")
data class DoctorEntity(
    @PrimaryKey
    @ColumnInfo(name = "id") val id: Long,
    @ColumnInfo(name = "contactName") val contactName: String?,
    @TypeConverters(CategoryConverter::class)
    @ColumnInfo(name = "categories") val categories: Categories?,
    @TypeConverters(CategoryConverter::class)
    @ColumnInfo(name = "languages") val languages: Categories?
) 
data class Categories(
    val categories: ArrayList<Long> = ArrayList()
)
class CategoryConverter {
    @TypeConverter
    fun toCategories(value: String?): Categories {
        if (value == null || value.isEmpty()) {
            return Categories()
        }
        val list: List<String> = value.split(",")
        val longList = ArrayList<Long>()
        for (item in list) {
            if (!item.isEmpty()) {
                longList.add(item.toLong())
            }
        }
        return Categories(longList)
    }
    @TypeConverter
    fun toString(categories: Categories?): String {
        var string = ""
        if (categories == null) {
            return string
        }
        categories.categories.forEach {
            string += "$it,"
        }
        return string
    }
}

Antwoord 9, autoriteit 2%

U moet ook deze TypeConvertermaken die uw Listnaar Stringzal converteren,

@TypeConverter
public List<CountryLang> toCountryLangList(String countryLangString) {
    if (countryLangString == null) {
        return (null);
    }
    Gson gson = new Gson();
    Type type = new TypeToken<List<CountryLang>>() {}.getType();
    List<CountryLang> countryLangList = gson.fromJson(countryLangString, type);
    return countryLangList;
}

En voor meer informatie kun je ook mijn andere antwoordbekijken.


Antwoord 10, autoriteit 2%

Als u een aangepaste klasse compatibel wilt maken (anders dan de ondersteunde), moet u een bidirectionele @TypeConverter opgeven converter die de aangepaste converteert naar een die bekend is bij Room en vice versa.

Als we bijvoorbeeld instanties van LatLng willen behouden:

Voorwaarde:implementation("com.squareup.moshi:moshi-kotlin:1.9.2")

Converters.kt

@TypeConverter
fun stringToLatLng(input: String?): LatLng? =
        input?.let { Moshi.Builder().build().adapter(LatLng::class.java).fromJson(it) }
@TypeConverter
fun latLngToString(input: LatLng): String? =
        Moshi.Builder().build().adapter(LatLng::class.java).toJson(input)

Room weet al hoe een string moet worden opgeslagen.

Met deze converters kunt u uw aangepaste typen in andere
query’s, net zoals je zou doen met primitieve typen

Locatie.kt

@Entity
data class Location(private val location: LatLng?)

GL

Bron


Antwoord 11, autoriteit 2%

De hier gegeven oplossingen zijn onvolledig, zodra je het proces hebt voltooid dat hier in het geaccepteerde antwoord wordt gegeven, moet je ook nog een annotatie toevoegen aan je Entity-klasse

@TypeConverters(Converter.class)
private List<String> brandId;

Dit moet worden geplaatst op het element dat de fout in Room DB veroorzaakt

veel plezier met coderen


Antwoord 12, autoriteit 2%

U kunt object naar string(json) type converter voor alle objecten vermijden door alleen deze type converter te gebruiken

@TypeConverter
    fun objectToJson(value: Any?) = Gson().toJson(value)

Ik gebruik dit en moet alleen converter definiëren voor string(json) om te object
bijv.

@TypeConverter
    fun stringToPersonObject(string: String?): Person? {
        return Gson().fromJson(string, Person::class.java)
    }

Antwoord 13

Men kan back & voort @TypeConverterals @TypeConverters:

public class DateConverter {
    @TypeConverter
    public long from(Date value) {
        return value.getTime();
    }
    @TypeConverter
    public Date to(long value) {
        return new Date(value);
    }
}

En pas ze dan toe op velden met:

@TypeConverters(DateConverter.class)

Antwoord 14

Heb hetzelfde probleem gehad. Wijzig de Listin ArrayList. De lijst is een interface en room kan deze niet opslaan.

Other episodes