I know that SharedPreferences has putString()
, putFloat()
, putLong()
, putInt()
and putBoolean()
. But I need to store an object that is of type Serializable
in SharedPreferences
. How can I achieve this?

- 1,654
- 3
- 16
- 30

- 21,744
- 6
- 60
- 75
7 Answers
The accepted answer is misleading, we can store serializable object into SharedPreferences by using GSON. Read more about it at google-gson.
you can add GSON dependency in Gradle file with:
compile 'com.google.code.gson:gson:2.7'
Here the snippet:
First, create your usual sharedPreferences:
//Creating a shared preference
SharedPreferences mPrefs = getPreferences(MODE_PRIVATE);
Saving from serializable object to preference:
Editor prefsEditor = mPrefs.edit();
Gson gson = new Gson();
String json = gson.toJson(YourSerializableObject);
prefsEditor.putString("SerializableObject", json);
prefsEditor.commit();
Get serializable object from preference:
Gson gson = new Gson();
String json = mPrefs.getString("SerializableObject", "");
yourSerializableObject = gson.fromJson(json, YourSerializableObject.class);

- 28,609
- 11
- 78
- 96
-
1Dangerous to use Json. In the event we change our data structure, than the deserialized data will not match. – Elye Sep 15 '18 at 03:16
-
1@Elye Any information stored in SharedPreferences is out of sync with runtime changes, like it does in any other DB. It is your duty as programer to take care and store the data when its change. Some DB like Realm and Room, may notify you about changes in DB but if data loaded than only you is the one who responsible to put it back to the DB. – Vitaliy A Sep 16 '19 at 14:40
In short you cant, try serializing your object to a private file, it amounts to the same thing. sample class below:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import android.app.Activity;
import android.content.Context;
/**
*
* Writes/reads an object to/from a private local file
*
*
*/
public class LocalPersistence {
/**
*
* @param context
* @param object
* @param filename
*/
public static void witeObjectToFile(Context context, Object object, String filename) {
ObjectOutputStream objectOut = null;
try {
FileOutputStream fileOut = context.openFileOutput(filename, Activity.MODE_PRIVATE);
objectOut = new ObjectOutputStream(fileOut);
objectOut.writeObject(object);
fileOut.getFD().sync();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (objectOut != null) {
try {
objectOut.close();
} catch (IOException e) {
// do nowt
}
}
}
}
/**
*
* @param context
* @param filename
* @return
*/
public static Object readObjectFromFile(Context context, String filename) {
ObjectInputStream objectIn = null;
Object object = null;
try {
FileInputStream fileIn = context.getApplicationContext().openFileInput(filename);
objectIn = new ObjectInputStream(fileIn);
object = objectIn.readObject();
} catch (FileNotFoundException e) {
// Do nothing
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
if (objectIn != null) {
try {
objectIn.close();
} catch (IOException e) {
// do nowt
}
}
}
return object;
}
}

- 1,516
- 13
- 19
-
Should `filename` in your code be an absolute path (e.g.: "/data/com.example.myapp/foobar.dat"), or should it be relative (e.g.: "foobar.dat")? – Matt Huggins Aug 30 '11 at 22:21
-
3just a filename, path separators are not allowed, as noted in the API doc http://developer.android.com/reference/android/content/Context.html#openFileOutput(java.lang.String, int) – Chris.D Aug 31 '11 at 14:18
-
1
-
I think it would just be context.getFileStreamPath(filename).delete(); – Chris.D Apr 09 '14 at 18:29
-
Just out of curiosity - should your FileInputStream & FileOutputStream be closed in your 'finally' blocks, as well as the ObjectInputStream & ObjectOutputStream ? – Tim Malseed Feb 27 '15 at 04:35
-
If you object is simple POJO you can convert object to JSON string and save it in shared preferences with putString().

- 211
- 2
- 2
It is possible to do it without a file.
I'm serializing the information to base64 and like this I'm able to save it as a string in the preferences.
The following code is Serializing a serializable objec to base64 string and vice versa: import android.util.Base64;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class ObjectSerializerHelper {
static public String objectToString(Serializable object) {
String encoded = null;
try {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(object);
objectOutputStream.close();
encoded = new String(Base64.encodeToString(byteArrayOutputStream.toByteArray(),0));
} catch (IOException e) {
e.printStackTrace();
}
return encoded;
}
@SuppressWarnings("unchecked")
static public Serializable stringToObject(String string){
byte[] bytes = Base64.decode(string,0);
Serializable object = null;
try {
ObjectInputStream objectInputStream = new ObjectInputStream( new ByteArrayInputStream(bytes) );
object = (Serializable)objectInputStream.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (ClassCastException e) {
e.printStackTrace();
}
return object;
}
}

- 2,324
- 1
- 16
- 14
-
The above class can be pasted into your POJO class and you can easily implement `public YourPojo getFromPreferences(Context context)` and `public void saveToPreferences(Context context)`, which uses the two methods above, along with `PreferenceManager.getDefaultSharedPreferences(context)` – Dale Mar 27 '18 at 18:56
We can create an easy to use syntax with Kotlin.
@Throws(JsonIOException::class)
fun Serializable.toJson(): String {
return Gson().toJson(this)
}
@Throws(JsonSyntaxException::class)
fun <T> String.to(type: Class<T>): T where T : Serializable {
return Gson().fromJson(this, type)
}
@Throws(JsonIOException::class)
fun SharedPreferences.Editor.putSerializable(key: String, o: Serializable?) = apply {
putString(key, o?.toJson())
}
@Throws(JsonSyntaxException::class)
fun <T> SharedPreferences.getSerializable(key: String, type: Class<T>): T? where T : Serializable {
return getString(key, null)?.to(type)
}
and then save any Serializable to SharedPreferences
using similar get/put()
Complete gist here Save Serializables in Shared Preferences with Kotlin and GSON
As mentioned in other answers, you might have to consider migration when structure of data class changes. Or atleast would have to change key that you use to store.

- 27,760
- 6
- 37
- 35
2020: If you want to save objects, then it's better to use Proto DataStore instead of SharedPreferences.
It brings great benefits over the “old” SharedPreferences, namely:
- Async API for storing and reading the data (Flow)
- Type-safety out of the box (Protocol Buffers)
- Safe to call from UI thread (Dispatchers.IO underneath)
And many other perks such as transactional API, which guarantee consistency.
Check out my blog post to see how to implement Proto DataStore easily

- 41
- 2
- 4
If your object is complex with nested objects and you may need to remove a nested object one day then this is a bad mechanism, as you will need to implement your own migration strategy (unless throwing all the data away is fine).
If it is a large amount of data, this mechanism lacks transaction support. So do you write your own? Or use a more appropriate storage mechanism? I strongly encourage a more appropriate storage mechanism such as filesystem of SQLite DB.

- 5,002
- 1
- 28
- 35