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 CountryLangs
opslaan (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%
@TypeConverter
herkent de klasse List
niet, dus u moet in plaats daarvan ArrayList
gebruiken, 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 TypeConverter
maken die uw List
naar String
zal 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
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 @TypeConverter
als @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 List
in ArrayList
. De lijst is een interface en room kan deze niet opslaan.