0

I have an issue with Room not recognizing my converter. Error:

Cannot figure out how to save this field into database. You can consider adding a type converter for it.  

I need to store some maps and sets in my database. What am I doing wrong? Does room not like interfaces or generics?
code: (sorry for all the fields and class name, they are a mixture of English and Czech to not have same names as some java classes):
Converter (only part)

public class MyConverter {
/**
 * makes a string like 1;2;3;5;4;8;1;6;8;4 from a collection of integers.
 */
@TypeConverter
public static @NonNull String toString(@NonNull Collection<Integer> c) {
    StringBuilder sb = new StringBuilder();
    for (Integer item : c) {
        sb.append(item.toString() + ";");
    }
    sb.delete(sb.length()-1,sb.length()-1);
    return sb.toString();
}

/**
 * makes a Set<Integer> from string like 1;2;3;4;5;6
 * @throws NumberFormatException on incorrect input
 */
@TypeConverter
public static@NonNull  Set<Integer> toIntegerSet(@NonNull String s) {
    Set<Integer> set = new LinkedHashSet<>();
    String[] split = s.split(";");
    try {
        for (String item : split) {
            set.add(Integer.parseInt(item));
        }
    }catch (NumberFormatException e){
        throw new NumberFormatException("Could not make set of integers (like 1;2;3;8;7) from \"" + s +"\"");
    }
    return set;
}
}  

Database:

@Database(entities = {SQLUkol.class,SQLPredmet.class,SQLList.class},version = 1)
@TypeConverters({MyConverter.class})
public abstract class AppDatabase extends RoomDatabase {
    public abstract MojeDAO mojeDao();
}  

One of the entities (getters, setters and constructors not included):

    @Entity(primaryKeys = {"id", "list_id"},
        indices = {@Index("list_id")},
        foreignKeys = @ForeignKey(entity = SQLList.class, parentColumns = "id", 
childColumns = "list_id", onDelete = ForeignKey.CASCADE),
        tableName = "ukols")
public class SQLUkol implements Comparable<SQLUkol> {
    @ColumnInfo(name = "list_id")
    private final int listID;
    private final int id;
    private String title;
    @ColumnInfo(name = "title_changed")
    private boolean titleChanged = false;
    private String notes;
    @ColumnInfo(name = "notes_changed")
    private boolean notesChanged = false;
    private boolean completed;
    @ColumnInfo(name = "completed_changed")
    private boolean completedChanged = false;
    private LocalDate date;
    @ColumnInfo(name = "date_changed")
    private boolean dateChanged = false;
    @Embedded
    private final SQLData data;
}
Vít Skalický
  • 612
  • 6
  • 16
  • I have downvoted this question because you have posted a considerable amount of code on here without specifying what is wrong with it. We expect to see what you expect the code to do, why you expect it to do this, what it is actually doing (with a full error message and stack trace where appropriate), and why it is wrong. Please [edit] your question to include this information, and then I will consider retracting my downvote. – Joe C Jan 27 '18 at 17:53
  • @joeC I have edited the question, could you please remove that downvote. – Vít Skalický Mar 19 '18 at 18:12

1 Answers1

2

Room does not like generics much. I had to do this:

@TypeConverter
public static String toString1(Map<String, String> m){
    ...
}

@TypeConverter
public static String toString2(Map<Integer, String> m){
    ...
}

@TypeConverter
public static String toString3(Set<Integer> s){
    ...
}

@TypeConverter
public static String toString4(List<Integer> l){
    ...
}

not just

@TypeConverter
public static String toString(Map m){
    ...
}

@TypeConverter
public static String toString(Collection<Integer> c){
    ...
}
Vít Skalický
  • 612
  • 6
  • 16