By Kristopher Johnson

2010-01-06 04:05:51 8 Comments

I'd like to store a JavaScript object in HTML5 localStorage, but my object is apparently being converted to a string.

I can store and retrieve primitive JavaScript types and arrays using localStorage, but objects don't seem to work. Should they?

Here's my code:

var testObject = { 'one': 1, 'two': 2, 'three': 3 };
console.log('typeof testObject: ' + typeof testObject);
console.log('testObject properties:');
for (var prop in testObject) {
    console.log('  ' + prop + ': ' + testObject[prop]);

// Put the object into storage
localStorage.setItem('testObject', testObject);

// Retrieve the object from storage
var retrievedObject = localStorage.getItem('testObject');

console.log('typeof retrievedObject: ' + typeof retrievedObject);
console.log('Value of retrievedObject: ' + retrievedObject);

The console output is

typeof testObject: object
testObject properties:
  one: 1
  two: 2
  three: 3
typeof retrievedObject: string
Value of retrievedObject: [object Object]

It looks to me like the setItem method is converting the input to a string before storing it.

I see this behavior in Safari, Chrome, and Firefox, so I assume it's my misunderstanding of the HTML5 Web Storage spec, not a browser-specific bug or limitation.

I've tried to make sense of the structured clone algorithm described in I don't fully understand what it's saying, but maybe my problem has to do with my object's properties not being enumerable (???)

Is there an easy workaround?

Update: The W3C eventually changed their minds about the structured-clone specification, and decided to change the spec to match the implementations. See So this question is no longer 100% valid, but the answers still may be of interest.


@Willem van der Veen 2019-06-27 08:55:53

Localstorage can only store key-value pairs where both of the keys and the values have to be strings. However, you can store object by serializing them to JSON strings and then deserialize them to JS objects when you retrieve them.

For example:

var testObject = { 'one': 1, 'two': 2, 'three': 3 };

// JSON.stringify turns a JS object into a JSON string, thus we can store it
localStorage.setItem('testObject', JSON.stringify(testObject));

// After we recieve a JSON string we can parse it into a JS object using JSON.parse
var jsObject = JSON.parse(localStorage.getItem('testObject')); 

Be aware of the fact that this will remove the established prototype chain. This is best shown via an example:

function testObject () { = 1;
  this.two = 2;
  this.three = 3;

testObject.prototype.hi = 'hi';

var testObject1 = new testObject();

// logs the string hi, derived from prototype

// the prototype of testObject1 is testObject.prototype

// stringify and parse the js object, will result in a normal JS object
var parsedObject = JSON.parse(JSON.stringify(testObject1));

// the newly created object now has Object.prototype as its prototype 
console.log(Object.getPrototypeOf(parsedObject) === Object.prototype);
// no longer is testObject the prototype
console.log(Object.getPrototypeOf(parsedObject) === testObject.prototype);

// thus we cannot longer access the hi property since this was on the prototype
console.log(parsedObject.hi); // undefined

@CMS 2010-01-06 04:25:58

Looking at the Apple, Mozilla and Mozilla again documentation, the functionality seems to be limited to handle only string key/value pairs.

A workaround can be to stringify your object before storing it, and later parse it when you retrieve it:

var testObject = { 'one': 1, 'two': 2, 'three': 3 };

// Put the object into storage
localStorage.setItem('testObject', JSON.stringify(testObject));

// Retrieve the object from storage
var retrievedObject = localStorage.getItem('testObject');

console.log('retrievedObject: ', JSON.parse(retrievedObject));

@oligofren 2013-10-07 18:48:42

do observe that any metadata will be removed. you just get an object with the key-value pairs, so any object with behaviour need to be rebuilt.

@Ashish Negi 2014-03-26 09:27:36

@CMS can setItem throw some exception if the data is over the capacity ?

@CoDEmanX 2014-07-23 16:54:51

... applies to objects with circular references only, JSON.stringify() expands the referenced object to its full "content" (implicitly stringified) in the object we stringify. See:

@Mark 2014-10-29 09:35:28

The problem with this approach are performance issues, if you have to handle large arrays or objects.

@jave.web 2015-07-06 20:03:52

@oligofren true, but as maja correctly suggested eval() => , this is one of the good use of , you can easily retrieve function code => store it as string and then eval() it back :)

@sheelpriy 2018-06-26 11:52:19

Better you make functions as setter and getter to localStorage, this way you will have better control and won't have to repeat the JSON parsing and all. it will even handle your (" ") empty string key/data case smoothly.

function setItemInStorage(dataKey, data){
    localStorage.setItem(dataKey, JSON.stringify(data));

function getItemFromStorage(dataKey){
    var data = localStorage.getItem(dataKey);
    return data? JSON.parse(data): null ;

setItemInStorage('user', { name:'tony stark' });
getItemFromStorage('user'); /* return {name:'tony stark'} */

@Vinod John 2016-06-02 14:00:16

Loop throught localstorage

var retrievedData = localStorage.getItem("MyCart");                 

retrievedData.forEach(function (item) {

@Brad 2017-04-01 20:05:10

Local Storage doesn't work this way. You're limited to strings... serialization is required.

@Flavien Volken 2018-05-30 07:34:26

For Typescript users willing to set and get typed properties:

 * Silly wrapper to be able to type the storage keys
export class TypedStorage<T> {

    public removeItem(key: keyof T): void {

    public getItem<K extends keyof T>(key: K): T[K] | null {
        const data: string | null =  localStorage.getItem(key);
        return JSON.parse(data);

    public setItem<K extends keyof T>(key: K, value: T[K]): void {
        const data: string = JSON.stringify(value);
        localStorage.setItem(key, data);

Example usage:

// write an interface for the storage
interface MyStore {
   age: number,
   name: string,
   address: {city:string}

const storage: TypedStorage<MyStore> = new TypedStorage<MyStore>();

storage.setItem("wrong key", ""); // error unknown key
storage.setItem("age", "hello"); // error, age should be number
storage.setItem("address", {city:"Here"}); // ok

const address: {city:string} = storage.getItem("address");

@Guria 2010-06-30 06:45:08

A minor improvement on a variant:

Storage.prototype.setObject = function(key, value) {
    this.setItem(key, JSON.stringify(value));

Storage.prototype.getObject = function(key) {
    var value = this.getItem(key);
    return value && JSON.parse(value);

Because of short-circuit evaluation, getObject() will immediately return null if key is not in Storage. It also will not throw a SyntaxError exception if value is "" (the empty string; JSON.parse() cannot handle that).

@zuallauz 2011-08-16 21:38:07

I just want to quickly add the usage as it wasn't immediately clear for me: var userObject = { userId: 24, name: 'Jack Bauer' }; And to set it localStorage.setObject('user', userObject); Then get it back from storage userObject = localStorage.getObject('user'); You can even store an array of objects if you want.

@Ian Davis 2011-11-01 17:02:45

when you do return this.getItem(key) && JSON.parse(this.getItem(key)), is it combining those two things? I've never seen this way of returning something.

@Guria 2011-11-01 21:04:19

It is just boolean expression. Second part are evaluated only if left one is true. In that case result of whole expression will be from right part. It is popular technic based on the way how boolean expressions are evaluated.

@PointedEars 2012-10-08 10:20:17

I do not see the point of the local variable and the shortcut evaluation here (minor performance improvements aside). If key is not in the Local Storage, window.localStorage.getItem(key) returns null – it does not throw an "Illegal access" exception – and JSON.parse(null) returns null as well – it does not throw an exception either, neither in Chromium 21 nor per ES 5.1 section 15.12.2, because String(null) === "null" which can be interpreted as a JSON literal.

@PointedEars 2012-10-08 10:42:24

The values in Local Storage are always primitive string values. So what this shortcut evaluation does handle is when someone stored "" (the empty string) before. Because it type-converts to false and JSON.parse(""), which would throw a SyntaxError exception, is not called.

@Ezeke 2013-01-16 12:15:23

This wont't work in IE8, so you're better of using the functions in the confirmed answer if you need to support it.

@Jordan Arseno 2013-07-01 22:54:06

FYI: The getObject() function barfs if the value undefined finds it's way into localStorage.

@Kai Noack 2014-11-27 20:03:54

To complete the answer, because who sets might also want to clear the storage: localStorage.clear(); Plus after the getObject() you check with: if(userObject) or if (!userObject). Disclaimer: I am noting this down because I tried undefined first.

@dr.Crow 2016-06-23 03:08:59

This throw exception when the value was undefined, maybe it's safe to check first if the value i.e. value || null this was also safe in JSON.parse(value);

@Timar Ivo Batis 2018-09-25 12:29:38

How did you know to set the prototype to Storage.prototype and not for instance localStorage.prototype or whatever else?

@JProgrammer 2011-08-23 03:52:02

There is a great library that wraps many solutions so it even supports older browsers called jStorage

You can set an object

$.jStorage.set(key, value)

And retrieve it easily

value = $.jStorage.get(key)
value = $.jStorage.get(key, "default value")

@SuperUberDuper 2016-08-30 00:57:28

$ is illegal !!!

@JProgrammer 2016-08-30 23:02:32

@SuperUberDuper jStorage requires Prototype, MooTools or jQuery

@Mac 2017-05-17 00:58:49

You can use localDataStorage to transparently store javascript data types (Array, Boolean, Date, Float, Integer, String and Object). It also provides lightweight data obfuscation, automatically compresses strings, facilitates query by key (name) as well as query by (key) value, and helps to enforce segmented shared storage within the same domain by prefixing keys.

[DISCLAIMER] I am the author of the utility [/DISCLAIMER]


localDataStorage.set( 'key1', 'Belgian' )
localDataStorage.set( 'key2', 1200.0047 )
localDataStorage.set( 'key3', true )
localDataStorage.set( 'key4', { 'RSK' : [1,'3',5,'7',9] } )
localDataStorage.set( 'key5', null )

localDataStorage.get( 'key1' )   -->   'Belgian'
localDataStorage.get( 'key2' )   -->   1200.0047
localDataStorage.get( 'key3' )   -->   true
localDataStorage.get( 'key4' )   -->   Object {RSK: Array(5)}
localDataStorage.get( 'key5' )   -->   null

As you can see, the primitive values are respected.

@Nmuta 2018-01-21 03:30:06

This is a brilliant resource and just what I need. I'm doing Ionic apps with AngularJS where I need to save certain javascript objects in localStorage and up to this point I've just been doing JSON.parse and JSON.stringify, and they work, but it's a bit more cumbersome than being able to just use a utility like this one. I'm going to try it.

@Shujaath Khan 2014-11-20 07:06:21

Using JSON objects for local storage:


var m={name:'Hero',Title:'developer'};
localStorage.setItem('us', JSON.stringify(m));


var gm =JSON.parse(localStorage.getItem('us'));

// Iteration of all local storage keys and values

for (var i = 0, len = localStorage.length; i < len; ++i) {


delete window.localStorage["us"];

@Thomas 2014-06-05 15:12:56

A small example of a library that use localStorage for keeping track of received messages from contacts:

// This class is supposed to be used to keep a track of received message per contacts.
// You have only four methods:

// 1 - Tells you if you can use this library or not...
function isLocalStorageSupported(){
    if(typeof(Storage) !== "undefined" && window['localStorage'] != null ) {
         return true;
     } else {
         return false;

// 2 - Give the list of contacts, a contact is created when you store the first message
 function getContacts(){
    var result = new Array();
    for ( var i = 0, len = localStorage.length; i < len; ++i ) {
    return result;

 // 3 - store a message for a contact
 function storeMessage(contact, message){
    var allMessages;
    var currentMessages = localStorage.getItem(contact);
    if(currentMessages == null){
        var newList = new Array();
        currentMessages = JSON.stringify(newList);
        var currentList =JSON.parse(currentMessages);
        currentMessages = JSON.stringify(currentList);
    localStorage.setItem(contact, currentMessages);

 // 4 - read the messages of a contact
 function readMessages(contact){

    var result = new Array();
    var currentMessages = localStorage.getItem(contact);

    if(currentMessages != null){
        result =JSON.parse(currentMessages);
    return result;

@zevero 2016-09-28 10:30:11

I made another minimalistic wrapper with only 20 lines of code to allow using it like it should:

localStorage.set('myKey',{a:[1,2,5], b: 'ok'});
localStorage.has('myKey');   // --> true
localStorage.get('myKey');   // --> {a:[1,2,5], b: 'ok'}
localStorage.keys();         // --> ['myKey']

@Tony Brix 2016-07-28 15:41:31

You can use ejson to store the objects as strings.

EJSON is an extension of JSON to support more types. It supports all JSON-safe types, as well as:

All EJSON serializations are also valid JSON. For example an object with a date and a binary buffer would be serialized in EJSON as:

  "d": {"$date": 1358205756553},
  "b": {"$binary": "c3VyZS4="}

Here is my localStorage wrapper using ejson

I added some types to my wrapper including regular expressions and functions

@pie6k 2016-06-23 11:28:07

I've modified one of top-voted answer a little. I'm a fan of having single function instead of 2 if it's not needed.

Storage.prototype.object = function(key, val) {
    if ( typeof val === "undefined" ) {
        var value = this.getItem(key);
        return value ? JSON.parse(value) : null;
    } else {
        this.setItem(key, JSON.stringify(val));

localStorage.object("test", {a : 1}); //set value
localStorage.object("test"); //get value

Also, if no value is set, it's returning null instead of false. false has some meaning, null does not.

@Mac 2018-01-22 17:35:29

Unlike the localStorage API, my library returns undefined when trying to get a non-existent key value. I agree false has meaning, but so does null. A variable set to null is absent any value (but it is set), whereas undefined is non-initialized.

@mar10 2016-06-16 17:10:51

Another option would be to use an existing plugin.

For example persisto is an open source project that provides an easy interface to localStorage/sessionStorage and automates persistence for form fields (input, radio buttons, and checkboxes).

persisto features

(Disclaimer: I am the author.)

@SpYk3HH 2016-07-11 19:28:11

Still working on my readme, but my version doesn't require jQuery, as it appears persisto does, but it does provide an alternative for dealing with jQuery element Objects. I will add more in the near future, as I work with it more, to help it further handle different jQuery Objects and maintain things like persistent data. Also, +1 for trying to provide a simpler solution! Also, it uses all the traditional methods of localStroage; exp: var lsh = new localStorageHelper(); lsh.setItem('bob', 'bill'); Also includes events.

@Seizefire 2016-05-21 16:48:56

To store an object, you could make a letters that you can use to get an object from a string to an object (may not make sense). For example

var obj = {a: "lol", b: "A", c: "hello world"};
function saveObj (key){
    var j = "";
    for(var i in obj){
        j += (i+"|"+obj[i]+"~");
    localStorage.setItem(key, j);
} // Saving Method
function getObj (key){
    var j = {};
    var k = localStorage.getItem(key).split("~");
    for(var l in k){
        var m = k[l].split("|");
        j[m[0]] = m[1];
    return j;
saveObj("obj"); // undefined
getObj("obj"); // {a: "lol", b: "A", c: "hello world"}

This technique will cause some glitches if you use the letter that you used to split the object, and it's also very experimental.

@shas 2015-12-04 06:17:54

Look this

Let's say you have the following array called movies:

var movies = ["Reservoir Dogs", "Pulp Fiction", "Jackie Brown", 
              "Kill Bill", "Death Proof", "Inglourious Basterds"];

Using the stringify function, your movies array can be turned into a string by using the following syntax:

localStorage.setItem("quentinTarantino", JSON.stringify(movies));

Notice that my data is being stored under the key called quentinTarantino.

Retrieving Your Data

var retrievedData = localStorage.getItem("quentinTarantino");

To convert from a string back to an object, use the JSON parse function:

var movies2 = JSON.parse(retrievedData);

You can call all of the array methods on your movies2

@kleopatra 2015-12-04 06:23:54

Note that link-only answers are discouraged, SO answers should be the end-point of a search for a solution (vs. yet another stopover of references, which tend to get stale over time). Please consider adding a stand-alone synopsis here, keeping the link as a reference.

@Kristopher Johnson 2015-12-04 19:10:23

Also note that your answer doesn't provide anything more than the existing five-year-old answer that has over 1500 votes. I appreciate that you are trying to answer my question, but please check whether your answer provides any value beyond that of other older answers.

@Rudie 2015-11-28 20:39:41

I made a thing that doesn't break the existing Storage objects, but creates a wrapper so you can do what you want. The result is a normal object, no methods, with access like any object.

The thing I made.

If you want 1 localStorage property to be magic:

var prop = ObjectStorage(localStorage, 'prop');

If you need several:

var storage = ObjectStorage(localStorage, ['prop', 'more', 'props']);

Everything you do to prop, or the objects inside storage will be automatically saved into localStorage. You're always playing with a real object, so you can do stuff like this:'more data');
storage.another.list.splice(1, 2, {another: 'object'});

And every new object inside a tracked object will be automatically tracked.

The very big downside: it depends on Object.observe() so it has very limited browser support. And it doesn't look like it'll be coming for Firefox or Edge anytime soon.

@doublejosh 2015-03-12 07:59:39

Recommend using an abstraction library for many of the features discussed here as well as better compatibility. Lots of options:

@maja 2014-11-19 09:51:42

Stringify doesn't solve all problems

It seems that the answers here don't cover all types that are possible in JavaScript, so here are some short examples on how to deal with them correctly:

//Objects and Arrays:
    var obj = {key: "value"};
    localStorage.object = JSON.stringify(obj);  //Will ignore private members
    obj = JSON.parse(localStorage.object);
    var bool = false;
    localStorage.bool = bool;
    bool = (localStorage.bool === "true");
    var num = 42;
    localStorage.num = num;
    num = +localStorage.num;    //short for "num = parseFloat(localStorage.num);"
    var date =; = date;
    date = new Date(parseInt(;
//Regular expressions:
    var regex = /^No\.[\d]*$/i;     //usage example: "No.42".match(regex);
    localStorage.regex = regex;
    var components = localStorage.regex.match("^/(.*)/([a-z]*)$");
    regex = new RegExp(components[1], components[2]);
//Functions (not recommended):
    function func(){}
    localStorage.func = func;
    eval( localStorage.func );      //recreates the function with the name "func"

I do not recommend to store functions because eval() is evil can lead to issues regarding security, optimisation and debugging. In general, eval() should never be used in JavaScript code.

Private members

The problem with using JSON.stringify() for storing objects is, that this function can not serialise private members. This issue can be solved by overwriting the .toString() method (which is called implicitly when storing data in web storage):

//Object with private and public members:
    function MyClass(privateContent, publicContent){
        var privateMember = privateContent || "defaultPrivateValue";
        this.publicMember = publicContent  || "defaultPublicValue";

        this.toString = function(){
            return '{"private": "' + privateMember + '", "public": "' + this.publicMember + '"}';
    MyClass.fromString = function(serialisedString){
        var properties = JSON.parse(serialisedString || "{}");
        return new MyClass( properties.private, properties.public );
    var obj = new MyClass("invisible", "visible");
    localStorage.object = obj;
    obj = MyClass.fromString(localStorage.object);

Circular references

Another problem stringify can't deal with are circular references:

var obj = {};
obj["circular"] = obj;
localStorage.object = JSON.stringify(obj);  //Fails

In this example, JSON.stringify() will throw a TypeError "Converting circular structure to JSON". If storing circular references should be supported, the second parameter of JSON.stringify() might be used:

var obj = {id: 1, sub: {}};
obj.sub["circular"] = obj;
localStorage.object = JSON.stringify( obj, function( key, value) {
    if( key == 'circular') {
        return "$ref""$";
    } else {
        return value;

However, finding an efficient solution for storing circular references highly depends on the tasks that need to be solved, and restoring such data is not trivial either.

There are already some question on SO dealing with this problem: Stringify (convert to JSON) a JavaScript object with circular reference

@Nadu 2015-02-10 20:25:37

Here some extented version of the code posted by @danott

It'll also implement delete value from localstorage and shows how to adds a Getter and Setter layer so instead of

localstorage.setItem(preview, true)

you can write

config.preview = true

Okay here were go:

var PT=Storage.prototype

if (typeof PT._setItem >='u') PT._setItem = PT.setItem;
PT.setItem = function(key, value)
  if (typeof value >='u')//..ndefined
    this._setItem(key, JSON.stringify(value));

if (typeof PT._getItem >='u') PT._getItem = PT.getItem;
PT.getItem = function(key)
  var ItemData = this._getItem(key)
    return JSON.parse(ItemData);
    return ItemData;

// Aliases for localStorage.set/getItem 
get =   localStorage.getItem.bind(localStorage)
set =   localStorage.setItem.bind(localStorage)

// Create ConfigWrapperObject
var config = {}

// Helper to create getter & setter
function configCreate(PropToAdd){
    Object.defineProperty( config, PropToAdd, {
      get: function ()      { return (  get(PropToAdd)      ) },
      set: function (val)   {           set(PropToAdd,  val ) }

// Usage Part
// Create properties

// Config Data transfer
config.preview = true


// delete
config.preview = undefined

Well you may strip the aliases part with .bind(...). However I just put it in since it's really good to know about this. I tooked me hours to find out why a simple get = localStorage.getItem; don't work

@Adrian May 2014-10-01 11:14:11 is a localStorage sugar layer that lets you write things like this:

var store = Rhaboo.persistent('Some name');
store.write('count', store.count ? store.count+1 : 1);
store.write('somethingfancy', {
  one: ['man', 'went'],
  2: 'mow',
  went: [  2, { mow: ['a', 'meadow' ] }, {}  ]
store.somethingfancy.went[1].mow.write(1, 'lawn');

It doesn't use JSON.stringify/parse because that would be inaccurate and slow on big objects. Instead, each terminal value has its own localStorage entry.

You can probably guess that I might have something to do with rhaboo ;-)


@seanp2k 2014-09-22 20:34:19

Improvement on @Guria 's answer:

Storage.prototype.setObject = function (key, value) {
    this.setItem(key, JSON.stringify(value));

Storage.prototype.getObject = function (key) {
    var value = this.getItem(key);
    try {
        return JSON.parse(value);
    catch(err) {
        console.log("JSON parse failed for lookup of ", key, "\n error was: ", err);
        return null;

@Andy Lorenz 2014-05-07 11:35:40

I arrived at this post after hitting on another post that has been closed as a duplicate of this - titled 'how to store an array in localstorage?'. Which is fine except neither thread actually provides a full answer as to how you can maintain an array in localStorage - however I have managed to craft a solution based on information contained in both threads.

So if anyone else is wanting to be able to push/pop/shift items within an array, and they want that array stored in localStorage or indeed sessionStorage, here you go:

Storage.prototype.getArray = function(arrayName) {
  var thisArray = [];
  var fetchArrayObject = this.getItem(arrayName);
  if (typeof fetchArrayObject !== 'undefined') {
    if (fetchArrayObject !== null) { thisArray = JSON.parse(fetchArrayObject); }
  return thisArray;

Storage.prototype.pushArrayItem = function(arrayName,arrayItem) {
  var existingArray = this.getArray(arrayName);

Storage.prototype.popArrayItem = function(arrayName) {
  var arrayItem = {};
  var existingArray = this.getArray(arrayName);
  if (existingArray.length > 0) {
    arrayItem = existingArray.pop();
  return arrayItem;

Storage.prototype.shiftArrayItem = function(arrayName) {
  var arrayItem = {};
  var existingArray = this.getArray(arrayName);
  if (existingArray.length > 0) {
    arrayItem = existingArray.shift();
  return arrayItem;

Storage.prototype.unshiftArrayItem = function(arrayName,arrayItem) {
  var existingArray = this.getArray(arrayName);

Storage.prototype.deleteArray = function(arrayName) {

example usage - storing simple strings in localStorage array:

localStorage.pushArrayItem('myArray','item one');
localStorage.pushArrayItem('myArray','item two');

example usage - storing objects in sessionStorage array:

var item1 = {}; = 'fred'; item1.age = 48;

var item2 = {}; = 'dave'; item2.age = 22;

common methods to manipulate arrays:

.pushArrayItem(arrayName,arrayItem); -> adds an element onto end of named array
.unshiftArrayItem(arrayName,arrayItem); -> adds an element onto front of named array
.popArrayItem(arrayName); -> removes & returns last array element
.shiftArrayItem(arrayName); -> removes & returns first array element
.getArray(arrayName); -> returns entire array
.deleteArray(arrayName); -> removes entire array from storage

@Velojet 2017-08-21 08:19:13

This is a very handy set of methods for manipulating arrays stored in localStorage or sessionStorage, and deserves much more credit than it's attracted. @Andy Lorenz Thanks for taking the time to share!

@Alex Grande 2011-01-21 18:29:16

Extending the Storage object is an awesome solution. For my API, I have created a facade for localStorage and then check if it is an object or not while setting and getting.

var data = {
  set: function(key, value) {
    if (!key || !value) {return;}

    if (typeof value === "object") {
      value = JSON.stringify(value);
    localStorage.setItem(key, value);
  get: function(key) {
    var value = localStorage.getItem(key);

    if (!value) {return;}

    // assume it is an object that has been stringified
    if (value[0] === "{") {
      value = JSON.parse(value);

    return value;

@Francesco Frapporti 2012-03-08 20:09:48

This was almost exactly what i needed. Just had to add if (value == null) { return false } before the comment, otherwise it resulted in error when checking the existence of a key on localStorage.

@rob_james 2012-03-13 00:06:59

This is pretty cool actually. Agree with @FrancescoFrapporti you need an if in there for null values. I also added an ' || value[0] == "[" ' test in case there in an array in there.

@Alex Grande 2012-11-02 15:15:19

Good point, I'll edit this. Although you don't need the null part, but if you do I recommend three ===. If you use JSHint or JSLint you will be warned against using ==.

@Ifedi Okonkwo 2015-06-20 08:13:34

And for non-ninjas (like me), could someone please provide a usage example for this answer? Is it: data.set('username': 'ifedi', 'fullname': { firstname: 'Ifedi', lastname: 'Okonkwo'});?

@Ifedi Okonkwo 2015-06-20 08:27:38

Yes indeed! When I overcame my desire to be spoon-fed, I took the code to test out, and got it. I think this answer is great because 1)Unlike the accepted answer, it takes time to do certain checks on the string data, and 2)Unlike the next one, it doesn't go extending a native object.

@Jimmy T. 2018-02-17 09:07:42

And then someone tries to store a string starting with {

@Alex Grande 2018-02-24 20:05:53

@JimmyT. that has kept me up at night in a cold sweat wondering if someone would do that. If you suggest a better regex or test for it being proper json in an efficient way, I'll edit the answer.

@Jimmy T. 2018-02-24 23:39:44

You could just stringify everything

@Fredrik_Macrobond 2019-01-01 15:51:13

Your set function won't work if you want to set a key to 0, "" or any other value that converts to false. Instead you should write: if (!key || value === undefined) return; This will also let you store a value of 'null' for a key.

@aster_x 2011-04-05 21:20:04

In theory, it is possible to store objects with functions:

function store (a)
  var c = {f: {}, d: {}};
  for (var k in a)
    if (a.hasOwnProperty(k) && typeof a[k] === 'function')
      c.f[k] = encodeURIComponent(a[k]);

  c.d = a;
  var data = JSON.stringify(c);
  window.localStorage.setItem('CODE', data);

function restore ()
  var data = window.localStorage.getItem('CODE');
  data = JSON.parse(data);
  var b = data.d;

  for (var k in data.f)
    if (data.f.hasOwnProperty(k))
      b[k] = eval("(" + decodeURIComponent(data.f[k]) + ")");

  return b;

However, Function serialization/deserialization is unreliable because it is implementation-dependent.

@PointedEars 2012-10-08 10:54:19

Function serialization/deserialization is unreliable because it is implementation-dependent. Also, you want to replace c.f[k] = escape(a[k]); with the Unicode-safe c.f[k] = encodeURIComponent(a[k]); and eval('b.' + k + ' = ' + unescape(data.f[k])); with b[k] = eval("(" + decodeURIComponent(data.f[k]) + ")");. The parentheses are required because your function, if serialized properly, is likely to be anonymous, which is not as-is a valid /Statement/ (so eval()) would throw a SyntaxError exception otherwise).

@PointedEars 2012-10-08 10:57:19

And typeof is an operator, do not write it as if it was a function. Replace typeof(a[k]) with typeof a[k].

@PointedEars 2012-10-08 16:17:41

In addition to applying my suggestions and emphasizing the unreliability of the approach, I have fixed the following bugs: 1. Not all variables were declared. 2. for-in was not filtered for own properties. 3. Code style, including referencing, was inconsistent.

@Michael 2014-01-06 19:34:47

@PointedEars what practical difference does this make? the spec says the use and placement of white space, line terminators, and semicolons within the representation String is implementation-dependent. I don't see any functional differences.

@PointedEars 2014-01-11 13:17:38

@Michael The part that you quoted starts with Note *in particular* that …. But the return value specification starts with An implementation-dependent representation of the function is returned. This representation has the syntax of a FunctionDeclaration. The return value can be function foo () {} – assuming a conforming implementation.

@danott 2011-04-26 13:00:50

You could also override the default Storage setItem(key,value) and getItem(key) methods to handle objects/arrays like any other data type. That way, you can simply call localStorage.setItem(key,value) and localStorage.getItem(key) as you normally would.

I haven't tested this extensively, but it has appeared to work without problems for a small project I've been tinkering with.

Storage.prototype._setItem = Storage.prototype.setItem;
Storage.prototype.setItem = function(key, value)
  this._setItem(key, JSON.stringify(value));

Storage.prototype._getItem = Storage.prototype.getItem;
Storage.prototype.getItem = function(key)
    return JSON.parse(this._getItem(key));
    return this._getItem(key);

@Schmuli 2011-09-07 12:32:21

It is considered bad practice to change native/build-in object APIs. See other answers for other solutions.

@Carl Smith 2014-06-08 14:07:34

Nice, assuming you never want use any libraries that depend on the spec.

@Justin Voskuhl 2010-01-06 04:42:47

You might find it useful to extend the Storage object with these handy methods:

Storage.prototype.setObject = function(key, value) {
    this.setItem(key, JSON.stringify(value));

Storage.prototype.getObject = function(key) {
    return JSON.parse(this.getItem(key));

This way you get the functionality that you really wanted even though underneath the API only supports strings.

@Garrett 2010-12-09 01:28:14

Wrapping CMS' approach up into a function is a good idea, it just needs a feature tests: One for JSON.stringify, one for JSON.parse, and one to test if localStorage can in fact set and retrieve an object. Modifying host objects is not a good idea; I would rather see this as a separate method and not as localStorage.setObject.

@PointedEars 2012-10-08 10:45:56

This getObject() will throw a SyntaxError exception if the stored value is "", because JSON.parse() cannot handle that. See my edit to Guria's answer for details.

@Sethen 2014-07-06 18:54:40

Just my two cents, but I'm pretty sure it's not a good idea to extend objects provided by the vendor like this.

Related Questions

Sponsored Content

34 Answered Questions

[SOLVED] Change an HTML5 input's placeholder color with CSS

45 Answered Questions

[SOLVED] How to check if an object is an array?

61 Answered Questions

[SOLVED] How do I correctly clone a JavaScript object?

69 Answered Questions

[SOLVED] What is the most efficient way to deep clone an object in JavaScript?

46 Answered Questions

38 Answered Questions

[SOLVED] How do I remove a property from a JavaScript object?

19 Answered Questions

[SOLVED] Checking if a key exists in a JavaScript object?

41 Answered Questions

[SOLVED] Detecting an undefined object property

7 Answered Questions

[SOLVED] Clearing localStorage in javascript?

6 Answered Questions

[SOLVED] How do I store an array in localStorage?

Sponsored Content