I need to use two arraylists in my database. Here is the entity class:
@Entity
public class User {
public int getId() {
return id;
}
@NonNull
public ArrayList<String> getValues(){
return values;
}
@NonNull
public ArrayList<String> getDates(){
return dates;
}
@NonNull
public String getType_counter() {
return type_counter;
}
@NonNull
public String getWhere_counter() {
return where_counter;
}
@PrimaryKey(autoGenerate = true)
public int id;
@ColumnInfo(name = "d")
@TypeConverters({Converters.class})
public ArrayList<String> dates; // arraylist here
@ColumnInfo(name = "value")
@TypeConverters({Converters.class})
public ArrayList<String> values; // arraylist here
@ColumnInfo(name = "type")
public String type_counter;
@ColumnInfo(name = "location")
public String where_counter;
}
I have created a TypeConverter class as described in
- rows with id's 6 and 7, as indicated by the crosses, lack the enclosing square brackets (see the following for how this data replicates the failure you are encountering).
However, if the fromArrayList
is modified to instead be :-
@TypeConverter
public static String fromArrayList(ArrayList<String> list) {
Log.d("TYPCONVERTER","Type Converter >>fromArrayList<< invoked. ArrayList had " list.size() " elements.");
Gson gson = new Gson();
return gson.toJson(list).replace("[","").replace("]","");
}
- i.e. it strips the '[' and ']'
- see rows 6 and 7
then running a test extraction, results in the exception that you are encountering (for the data):-
2022-07-26 10:27:15.328 28959-28959/a.a.so73110961javaroomlisttypeconverters E/AndroidRuntime: FATAL EXCEPTION: main
Process: a.a.so73110961javaroomlisttypeconverters, PID: 28959
java.lang.RuntimeException: Unable to start activity ComponentInfo{a.a.so73110961javaroomlisttypeconverters/a.a.so73110961javaroomlisttypeconverters.MainActivity}: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 1 column 2 path $
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3449)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Caused by: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 1 column 2 path $
The fix is to ascertain where you are saving a string without the enclosing square brackets (and it is very unlikely the Type Converter)
Changing to use:-
@Query("SELECT * FROM User "
"WHERE "
" substr(value,1,1) = '[' "
"AND substr(value,length(value),1) = ']' "
"AND substr(d,1,1) = '[' "
"AND substr(d,length(d),1) = ']' "
"AND id=:id "
";")
LiveData<User> getValidUser(int id);
circumvents the failure BUT would return nothing for a User that has the incorrect data stored.
Using App Inspection you could run the following query to ascertain which rows would cause and issue :-
SELECT * FROM user WHERE substr(d,1,1) <> '[' OR substr(d,length(d),1) <> ']' OR substr(value,1,1) <> '[' OR substr(value,length(value),1) <> ']';
e.g.