Android JSON parsing with GSON crash: LinkedTreeMap cannot be cast to Object - android

I am trying to store a list of objects into SharedPreferences, so therefore am using Gson to convert the list of objects into JSON and back again. However, when I store then retrieve the list of objects and the ListView's adapter is applied to the new List, I get the following error:
java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to appuccino.simplyscan.Objects.Folder
at appuccino.simplyscan.Extra.DocumentAdapter.getView(DocumentAdapter.java:117)
where the error points at this line in the list's adapter:
Folder folder = folderList.get(position);
When storing the object list, I am using the following:
//folderList is a List<Folder> folderList = new ArrayList<>();
folderList.add(0, newFolder);
Gson gson = new Gson();
String newFoldersJson = gson.toJson(folderList);
PrefManager.putString(PrefManager.FOLDER_JSON, newFoldersJson);
where the last line simply stores the string into SharedPreferences. When retrieving the list from SharedPreferences, I am using the following:
public static List<Folder> loadFolders(MainActivity main){
//JSON containing a list of folder objects
String foldersJSON = PrefManager.getString(PrefManager.FOLDER_JSON, "");
if(!foldersJSON.isEmpty()){
Gson gson = new Gson();
List<Folder> folderList = gson.fromJson(foldersJSON, List.class);
return folderList;
}
return new ArrayList<>();
}
If it helps, here is how my Folder class is defined:
public class Folder {
private String name;
private List<String> docNameList;
private transient List<Document> docList;
public Folder(String n) {
name = n;
docList = new ArrayList<>();
docNameList = new ArrayList<>();
}
}

Not a answer to your question, but a suggestion. I am also trying to work with json in Android recently and researched a lot about which one to use jackson or gson. Seems like there are 2 advantages of jackson:
Performance of jackson is better than gson.
If you are using the same on server side then you get consistency.
Ref:
[be-lazy-productive-android][1]
http://java.dzone.com/articles/be-lazy-productive-android

Related

populating arraylist of arraylist

I have an arraylist of arraylist which I am tring to populate but its not working.The response is being fetched from server.the response comes as follows
[{"QKey":"1234","OptionLabel":"Ground Floor","optionValue":"0"},{"QKey":"5678","OptionLabel":"1st Floor","optionValue":"1"}
I am trying to fetch it,add it in arraylist and populate but it seems to be not working
this is my code
String dropDownResponse=readFromFile(2);
Log.d("Reading from file",dropDownResponse);
JSONArray jsonArray = new JSONArray(dropDownResponse);
formModel.setName(rowLabel);
formModel.setIsMandatory(isMandatory);
formModel.setInputType(inputType);
/* formModel.setName("SAMPLE LABEL");
formModel.setIsMandatory("Y");
formModel.setInputType("selectbox");*/
spinnerList.add(formModel);
spinnerPopulationList.get(spinnerList.size()-1).set(0,rowLabel);
for(int j=0;j<jsonArray.length();j++)
{
JSONObject jsonObject = jsonArray.getJSONObject(j);
spinnerRowId=jsonObject.getString("QKey");
Log.d("QKey",spinnerRowId);
optionLabel=jsonObject.getString("OptionLabel");
Log.d("Option Label",optionLabel);
if(rowId.equals(spinnerRowId))
{
spinnerPopulationList.get(spinnerList.size()-1).set(spinnerPopulationList.get(spinnerList.size()-1).size()-1,optionLabel);
}
}
for(int h=0;h<spinnerPopulationList.get(spinnerList.size()-1).size();h++)
{
Log.d("spinner item"+rowLabel+"["+h+"]",spinnerPopulationList.get(spinnerList.size()-1).get(h));
}
this line in the code shows indexOutOfBoundException
if(rowId.equals(spinnerRowId))
{
spinnerPopulationList.get(spinnerList.size()-1).set(spinnerPopulationList.get(spinnerList.size()-1).size()-1,optionLabel);
}
I don't think you need a two dimensional AllayList to accomodate this json. This is just an array of objects. You can use Gson to parse it quite easily.
You will need a couple of response classes like
class ResponseObj {
private String Qkey;
private String OptionLabel;
private String optionValue;
//Constructor(s), getters and setters
}
class Response {
private ArrayList<ResponseObj> objects = new ArrayList<>();
//Constructor(s), getters and setters
}
Then you can use Gson to parse the json and make an object out of it. You can use something like this where you are getting the response from server.
Response response = gson.fromJson(YOUR_JSON, Response.class);
for(ResponseObj object : response.getObjects()) {
//In this loop, you are iterating over each object in your json
//which looks like
//{"QKey":"1234","OptionLabel":"Ground Floor","optionValue":"0"}
doSomething(object);
doSomethingWithKey(object.getQKey());
}
Here is how you can use Gson in your project.

Serialization of Custom Class Using GSON

I list of objects of a custom class which i am trying to serialize using json but the values once serialized are 0 and not the actual values that are stored in the list.
MyCustom Class
public class CustomClass extends RealmObject {
#Expose()
#SerializedName("startID")
private int startMessageID;
#Expose()
#SerializedName("endID")
private int endMessageID;
#Expose(serialize = false)
private boolean syncing = false;
}
The following is what i use to serialize the list.
GsonBuilder builder = new GsonBuilder();
builder.excludeFieldsWithoutExposeAnnotation();
Gson gson = builder.create();
Type listType = new TypeToken<List<CustomClass >>() {
}.getType();
Log.i("Json", gson.toJson(syncModelList, listType));
The above code produces an output of
[{"endID":0,"startID":0},{"endID":0,"startID":0}]
The structure is correct but my values are lost,i have checked the values before serialization and they are correct and exist.
It's because Gson can't serialize a managed Realm object. You need to convert it to an unmanaged object first, like this:
new Gson().toJson(realm.copyFromRealm(managedModel));
Have a look at this answer for a full explanation Android: Realm + Retrofit 2 + Gson

Parse Json containing a list

I have a trouble finding a way how to parse this JSON.
{
"token":"3c7dbdc69c02eb365b2900d3e5027a08c79fce43",
"profiles":["User","PartnerUser"],
"status":"OK"
}
Plz,i need your hepl. I find atrouble with this "profiles":["User","PartnerUser"]
create a class that represent that json file and then parse it via GSon library:
Possible scenario:
Result.class
public class Result{
String token;
List<String> profiles;
String status;
//getter and setter
}
to parse json:
Gson gson = new Gson();
Result result = gson.fromJson(json, Result.class);
ArrayList<String> profiles = new ArrayList();
profiles = result.getProfiles();
check this
Are you using some library to perform JSON parsing?
If not, you can use the getJSONArray(..) method passing "profiles" as name of the array

Error occuring on some Android devices involving GSON

The problem appears to happen only on Samsung devices. However it did happen on one non Samsung device. I've been trying to replicate the issue on my phone (Nexus 5, vanilla lollipop) but it doesn't happen.
This saves an ArrayList of an ArrayList of an ArrayList of BusEntrys
private static void saveDataList(ArrayList<ArrayList<ArrayList<BusEntry>>> list, String key1){
SharedPreferences appSharedPrefs = PreferenceManager
.getDefaultSharedPreferences(RO.mainActivity.getApplicationContext());
SharedPreferences.Editor prefsEditor = appSharedPrefs.edit();
ArrayList<ArrayList<ArrayList<BusEntry>>> entries = list;
Gson gson = new Gson();
String jsonEntries = gson.toJson(entries);
//Log.d("TAG", "jsonCars = " + jsonEntries);
prefsEditor.putString(key1, jsonEntries);
prefsEditor.commit();
}
This loads an ArrayList of an ArrayList of an ArrayList of BusEntrys
private static Object getDataList(String key, int task){
SharedPreferences appSharedPrefs = PreferenceManager
.getDefaultSharedPreferences(RO.mainActivity.getApplicationContext());
String jsonString = appSharedPrefs.getString(key, ""); // TODO use empty string as an if statement to determine if you need to recache
Type type;
type = new TypeToken<ArrayList<ArrayList<ArrayList<BusEntry>>>>(){}.getType();
Gson gson = new Gson();
return gson.fromJson(jsonString, type);
}
Error Stack
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.joltimate.umdshuttle/com.joltimate.umdshuttle.MainActivity}: com.google.a.aa: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was NUMBER at line 1 column 7 path $[0].b
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3119)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3218)
at android.app.ActivityThread.access$1000(ActivityThread.java:198)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1676)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6837)
at java.lang.reflect.Method.invoke(Method.java)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)
Caused by: com.google.a.aa: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was NUMBER at line 1 column 7 path $[0].b
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read()
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write()
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read()
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read()
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read()
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read()
at com.google.gson.Gson.doubleAdapter()
at com.google.gson.Gson.doubleAdapter()
at com.google.gson.Gson.doubleAdapter()
at com.joltimate.umdshuttle.Data.DataStorage.saveDataList()
at com.joltimate.umdshuttle.Data.DataStorage.getAllData()
at com.joltimate.umdshuttle.Data.DataStorage.saveDataList()
at com.joltimate.umdshuttle.MainActivity.onCreate()
You have:
Type type;
type = new TypeToken<ArrayList<ArrayList<ArrayList<BusEntry>>>>(){}.getType();
Gson gson = new Gson();
return gson.fromJson(jsonString, type);
From the documentation:
Gson gson = new Gson();
int[] ints = {1, 2, 3, 4, 5};
(Serialization)
gson.toJson(ints); ==> prints [1,2,3,4,5]
(Deserialization)
int[] ints2 = gson.fromJson("[1,2,3,4,5]", int[].class);
==> ints2 will be same as ints
It would seem you are not returning the expected type.
I would suggest something like the following:
class SpecialArrayType{
private ArrayList<ArrayList<BusEntry>> specialArrayType;
public void setSpecialArrayType(ArrayList<ArrayList<BusEntry>> list){
this.specialArrayType = list;
}
public ArrayList<ArrayList<BusEntry>> getSpecialArrayType(){
return specialArrayType;
}
}
// Get the array list as a special type, then deal with the nested lists.
ArrayList<SpecialArrayType> lists = new ArrayList<SpecialArrayType>();
Type type = new TypeToken<ArrayList<SpecialArrayType>>(){}.getType();
Gson gson = new Gson();
lists = gson.fromJson(jsonString, type);
ArrayList<ArrayList<ArrayList<BusEntry>>> returnList = new ArrayList<ArrayList<ArrayList<BusEntry>>>();
// Loop through special array list to populate info from nested array lists.
for(SpecialArrayType list1: lists){
// We have these items in our outer array list, we want to add them to our
// return list.
returnList.Add(list1);
// The next nested array list.
list1 = new ArrayList<ArrayList<BusEntry>>();
for(ArrayList<BusEntry> list2: list1){
// Populate each specialArrayType with an array list of array list of BusEntries.
list1.Add(list2);
// Find each nested array list of bus entries.
list2= new ArrayList<BusEntry>> ();
for(BusEntry entry: list2){
list2.Add(entry);
}
}
}
return returnList;
So you are returning the fully nested data.
Add following library in your android studio project instead of putting manual library in library folder.
compile 'com.google.code.gson:gson:2.3.1'
and if you are trying to store arraylist or class object in sharedpreferences using GSON then try this tutorial : click here

How can I cast a stringarray to an ArrayList in Android?

I'm saving a list with json in SharedPreferences. This works just fine, but when I try to load it Android Studio tells me I can't
private List<AppInfo> apps;
apps = new ArrayList<AppInfo>();
// Storing in method
ArrayList<String> lollist = new ArrayList<>();
lollist = new ArrayList<>(Arrays.asList(String.valueOf(apps)));
setStringArrayPref(this, "urls", lollist);
// Loading which doesn't work
lollist = getStringArrayPref(this, "urls");
apps = (String[]) lollist.toArray();
The error I get is
Required: java.util.list <com.....AppInfo>
Found: java.lang.String[]
How may I do this?
You might wanna use Gson library for this.
Which provides you easier one line options to convert a data structure to Json and vice versa.
Usage :
private Gson gson = new Gson();
private List<AppInfo> apps = new ArrayList<AppInfo>();
String jsonString = gson.toJson(apps); //You may store this string in your shared preference
Type type = new TypeToken<List<AppInfo>>() {}.getType();
apps = gson.fromJson(jsonString, type);
NOTE :
You should Expose the variables in your Data model class to use Gson. Like this.
#Expose
private String name;

Categories

Resources