Постоянная библиотека телефона Android - Ошибка ошибки TypeConverter: не удается определить, как сохранить поле в базу данных "

Мне не удалось создать типКонвертер в комнате из-за ошибки. Кажется, я следую за документами. Я хотел бы преобразовать список в строку json. давайте посмотрим на мою сущность:

      @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;
    }

}

country_lang - это то, что я хотел бы преобразовать в строку json. Поэтому я создал следующий конвертер: 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);
}}

тогда проблема в том, что я помещаю @TypeConverters ({Converters.class}), я продолжаю получать ошибку. Но официально это то, где я разместил аннотацию, чтобы зарегистрировать типКонвертер:

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

Ошибка, которую я получаю:

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

Ответ 1

Это обычная проблема, которую я видел с момента объявления Room. Room не поддерживает возможность хранения списков напрямую, а также возможность конвертировать в/из списков. Он поддерживает преобразование и хранение POJO.

В этом случае решение прост. Вместо сохранения List<CountryLang> вы хотите сохранить CountryLangs (обратите внимание на 's')

Я сделал быстрый пример решения здесь:

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;
    }
}

Это POJO - это инверсия вашего предыдущего объекта. Это объект, который хранит список языков. Вместо списка объектов, которые хранят ваш язык.

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;
    }
}

Этот конвертер принимает список строк и преобразует их в разделенную запятыми строку, которая будет храниться в одном столбце. Когда он извлекает строку из SQLite db для преобразования обратно, он разбивает список на запятые и заполняет CountryLangs.

Забудьте обновить версию RoomDatabase после внесения этих изменений. У вас остальная конфигурация правильная. Счастливая охота с остальной частью вашей работы настойчивостью в номере.

Ответ 2

Имела ту же ошибку: "Невозможно выяснить, как сохранить это поле в базе данных" при попытке добавить поле "Дата". Пришлось добавить к нему класс конвертера и добавить в поле аннотацию @TypeConverters.

Пример:

WordEntity.java

import android.arch.persistence.room.TypeConverters;

    @Entity
    public class WordEntity {

        @PrimaryKey(autoGenerate = true)
        public int id;
        private String name;
        @TypeConverters(DateConverter.class)
        private Date createDate;

DateConverter.java:

import android.arch.persistence.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();
    }
}

Ответ 3

@TypeConverter не распознает класс List, поэтому вместо этого следует использовать ArrayList, поэтому вам не нужна дополнительная оболочка для списка, который вы хотите сохранить.

Ответ 4

Я использовал преобразователи типов, описанные здесь (статья на Medium.com), и это сработало:

@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);
    }

Ответ 5

Пример Kotlin (не хорошо, но просто, 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
    }
}

Ответ 6

Вы также должны создать этот TypeConverter который преобразует ваш List в String,

@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;
}

И для получения дополнительной информации вы также можете проверить мой другой ответ.

Ответ 7

Была такая же проблема. Измените List на ArrayList. Список представляет собой интерфейс, и комната не может его сохранить.

Ответ 8

просто аннотирование этого объекта с помощью @Embedded решило мою проблему. Как это

@Embedded
private List<CrewListBean> crewList;