Gson and Android

Gson is a lightweight and open-source library from Google which takes care of serializing Plain Old Java Objects (POJO’s) to JSON, and JSON to POJO’s.  Since it is written in Java and has a JAR file available, I found it can also be a great choice for the Android platform as well.  The JAR file weighs in at 190KB, so it will add a little bit of bloat to your app.  However, I think the ease of use is worth the extra space that the code takes up.  With the use of ProGuard, most of the unneeded code will be removed from your APK file anyways.

In my Android app MoPhotos, I have a need to persist some user preferences that the built-in persistence mechanisms were either too simple (preferences) or too heavy-weight (SQLite).  This particular set of preferences is a set of directories that a user has selected for my app to scan and display photos for.

To persist each directory, I first created a model class that represents the data I want to persist for each user selection:

public class Filesystem
{
    private String uri;
    private boolean enabled;
    private transient List photoDirectories = null;
}

By default, any fields in the class will be included in the serialization/deserialization results.  To add additional fields that you do not want to be persisted, use the “transient” keyword to have Gson ignore that field.

The next step was to load the JSON file when the Activity was started.  The loadFilesystemConfiguration method is called during onCreate.  With Gson, this is pretty easy:

private void loadFilesystemConfiguration()
{
    Gson gson = new Gson(); //1
    FileInputStream fis = null; 
    try { 
        fis = this.application.openFileInput("Filesystems"); //2
        Type collectionType = new TypeToken<Collection<Filesystem>>(){}.getType(); //3 
        List filesystems = gson.fromJson(new InputStreamReader(fis), collectionType); //4
        if(filesystems != null) { 
            this.photoFileSystems.addAll(filesystems);
        }
    }
    catch(JsonIOException e) { ...  }
    catch(JsonSyntaxException e) { ...  }
    catch (FileNotFoundException e) { ...  }
    finally { 
        try { 
            if(fis != null)
                fis.close(); //5
        }
        catch (IOException e)  { ...  }
    }
}
Notes for the above snippit:
//1:  Create the Gson class instance which will deserialize the JSON into our POJO’s
//2:  Open the file storing the JSON string.  By default, I am using the app’s internal file storage space to store the JSON file in a file called “Filesystems”.  The name can be anything you want.
//3:  Because I’m persisting a list of POJO’s, I needed to create this Type object to reflect the collection type needed to give Gson the proper context.
//4:  Deserialize the JSON into a List object.
//5:  Make sure you close the file in the finally block.

Serializing the list of Filesystem objects is just as simple.  In the onDestroy method, the saveFilesystemConfiguration method is called:

public void saveFilesystemConfiguration()
{
    Gson gson = new Gson();
    String filesystemData = gson.toJson(this.photoFileSystems);  //1

    FileOutputStream fos = null;
    try {
        fos = this.application.openFileOutput("Filesystems", Context.MODE_PRIVATE);
        fos.write(filesystemData.getBytes());  //2
    }
    catch (FileNotFoundException e)  { ...  }
    catch (IOException e)  { ...  }
    finally {
        try {
            if(fos != null) fos.close();
        }
        catch (IOException e)  { ...  }
    }
}

Notes for the above snippit:

//1:  Serialize our List array to JSON into a string.
//2:  Write the JSON string to the filesystem, using the same file name as before, located in the app’s internal storage location.

Gson turned out to be a nice way to serialize this list of objects for my app.  In fact, I ended up using this same general design in 2 other places as well.  Eventually I realized that this mechanism, coupled with a ListActivity and ArrayAdapter, could be implemented as a more general mechanism for storing lists of user preferences.  Maybe next release.

This is probably a very simple use for Gson.  I could have used a simple flat text file and read the directories line-by-line.  However, Gson does make the code a bit easier, and I learned a new skill in the process that might prove helpful for a more complex future scenario.  Gson does add a little bit of weight to your APK, so you’ll have to weigh the cost/benefits against that.

Leave a Reply