192

SessionStorage and LocalStorage allows to save key/value pairs in a web browser. The value must be a string, and save js objects is not trivial.

var user = {'name':'John'};
sessionStorage.setItem('user', user);
var obj = sessionStorage.user; // obj='[object Object]' Not an object

Nowadays, you can avoid this limitation by serializing objects to JSON, and then deserializing them to recover the objects. But the Storage API always pass through the setItem and getItem methods.

sessionStorage.setItem('user', JSON.stringify(user));
var obj = JSON.parse(sessionStorage.getItem('user')); // An object :D

Can I avoid this limitation?

I just want to execute something like this:

sessionStorage.user.name; // 'John'
sessionStorage.user.name = 'Mary';
sessionStorage.user.name // 'Mary'

I have tried the defineGetter and defineSetter methods to intercept the calls but its a tedious job, because I have to define all properties and my target is not to know the future properties.

Nicu Surdu
  • 8,172
  • 9
  • 68
  • 108
Ferran Basora
  • 3,097
  • 3
  • 19
  • 13
  • 1
    I've thought of that myself. I suppose a lot of people have. But I don't think getter and setter methods are too much of a burden. BTW; you can serialize and parse with JavaScript and MS is finally supporting the same standard objects as everyone else. The days of need for packages like JSON and jQuery are coming rapidly to an end. – Roger F. Gay Mar 18 '13 at 07:45
  • 1
    I guess I don't see the limitation. It may seem like overkill to use JSON.stringify and JSON.parse if you only ever have trivial objects, but if you have even good-sized data objects those two methods are doing a lot of work for you. – Robusto Aug 05 '13 at 15:26
  • 5
    "Can I avoid this limitation?" seems like a question – sonicblis Jun 19 '14 at 21:17
  • 1
    Well limitation or not, this question helped me solve a problem, so thanks. – Matt West Jun 28 '16 at 19:32
  • Just wondering if a decade later you still stand by your accepted answer? The top voted answer is 5 times more popular. – WinEunuuchs2Unix Mar 30 '22 at 01:26

10 Answers10

151

The solution is to stringify the object before calling setItem on the sessionStorage.

var user = {'name':'John'};
sessionStorage.setItem('user', JSON.stringify(user));
var obj = JSON.parse(sessionStorage.user);
Community
  • 1
  • 1
Ron
  • 1,748
  • 2
  • 12
  • 11
117

Could you not 'stringify' your object...then use sessionStorage.setItem() to store that string representation of your object...then when you need it sessionStorage.getItem() and then use $.parseJSON() to get it back out?

Working example http://jsfiddle.net/pKXMa/

bumbumpaw
  • 2,522
  • 1
  • 24
  • 54
afreeland
  • 3,889
  • 3
  • 31
  • 42
  • This works for me. I get a working Json object after calling $.parseJSON() – Olafur Tryggvason Nov 24 '14 at 15:46
  • Some systems like Web Api authentication return objects in the form of Object { propertyOneWithoutQuotes : "", ... propertyNWithoutQuotes : "" } which need to go through "stringify". If there are multiple sources it might be better to use stringify to standardize the data. – Jelgab Jan 28 '15 at 16:55
  • This is very good answer. It is good to use JSON.stringify() to serialize object and store in sessionStorage. Then, it use $.parseJSON() to de-serialize the string to get the object. – Thomas.Benz Dec 03 '16 at 00:21
  • Just tried your fiddle and I get `undefined undefined is undefined years old.` – James Nov 16 '21 at 22:38
  • @Thomas.Benz You are a Genius !!! Thank you so much. Your simple answer helped me solve an important problem in our code. ("It is good to use JSON.stringify() to serialize object and store in sessionStorage. Then, it use $.parseJSON() to de-serialize the string to get the object."(SIC)) – Sankar Natarajan Mar 07 '22 at 13:22
23

Either you can use the accessors provided by the Web Storage API or you could write a wrapper/adapter. From your stated issue with defineGetter/defineSetter is sounds like writing a wrapper/adapter is too much work for you.

I honestly don't know what to tell you. Maybe you could reevaluate your opinion of what is a "ridiculous limitation". The Web Storage API is just what it's supposed to be, a key/value store.

Ryan Olds
  • 4,847
  • 28
  • 24
  • 10
    Sorry if I have used an inappropriate word with 'ridiculous'. Replace it with 'could be so interesting'. I think that the webStorage is one of the most exciting improvement of the new web. But save only strings in the value key-map I think is a limitation. It seems like a cookies' sequel. I know that the Storage is a specification non only for Javascript language, but serialize objects could be an interesting improvement. What do you think? – Ferran Basora Jun 02 '11 at 09:18
  • 2
    If JSON isn't enough, you could always write your own object serialization methods. – Ryan Olds Jun 02 '11 at 14:07
19

This is a dynamic solution which works with all value types including objects :

class Session extends Map {
  set(id, value) {
    if (typeof value === 'object') value = JSON.stringify(value);
    sessionStorage.setItem(id, value);
  }

  get(id) {
    const value = sessionStorage.getItem(id);
    try {
      return JSON.parse(value);
    } catch (e) {
      return value;
    }
  }
}

Then :

const session = new Session();

session.set('name', {first: 'Ahmed', last : 'Toumi'});
session.get('name');
Abdennour TOUMI
  • 87,526
  • 38
  • 249
  • 254
6

Use case:

 sesssionStorage.setObj(1,{date:Date.now(),action:'save firstObject'});
 sesssionStorage.setObj(2,{date:Date.now(),action:'save 2nd object'}); 
 //Query first object
  sesssionStorage.getObj(1)
  //Retrieve date created of 2nd object
  new Date(sesssionStorage.getObj(1).date)

API

Storage.prototype.setObj = function(key, obj) {

        return this.setItem(key, JSON.stringify(obj))
    };
    
    Storage.prototype.getObj = function(key) {
        return JSON.parse(this.getItem(key))
    };
Community
  • 1
  • 1
Abdennour TOUMI
  • 87,526
  • 38
  • 249
  • 254
  • 4
    I thought one of the best practices in javascript was to not prototype objects that you do not own. Using Storage.prototype.setObj seems like a bad idea. – britztopher Jan 13 '15 at 15:44
  • 4
    just adding the obligatory.. make sure you don't add this prototype code - and rely on it exclusively - without first checking if the browser supports it Storage: `if (typeof (Storage) !== "undefined"){ /* browser supports it */ }` – JoeBrockhaus Apr 09 '15 at 14:26
4
    var user = {'name':'John'};
    sessionStorage['user'] = JSON.stringify(user);
    console.log(sessionStorage['user']);
Jijo Paulose
  • 1,896
  • 18
  • 20
4

Session storage cannot support an arbitrary object because it may contain function literals (read closures) which cannot be reconstructed after a page reload.

Igor Urisman
  • 717
  • 1
  • 6
  • 22
4

You can create 2 wrapper methods for saving and retrieving object from session storage.

function saveSession(obj) {
  sessionStorage.setItem("myObj", JSON.stringify(obj));
  return true;
}

function getSession() {
  var obj = {};
  if (typeof sessionStorage.myObj !== "undefined") {
    obj = JSON.parse(sessionStorage.myObj);
  }
  return obj;
}

Use it like this:- Get object, modify some data, and save back.

var obj = getSession();

obj.newProperty = "Prod"

saveSession(obj);
GorvGoyl
  • 42,508
  • 29
  • 229
  • 225
3

You could also use the store library which performs it for you with crossbrowser ability.

example :

// Store current user
store.set('user', { name:'Marcus' })

// Get current user
store.get('user')

// Remove current user
store.remove('user')

// Clear all keys
store.clearAll()

// Loop over all stored values
store.each(function(value, key) {
    console.log(key, '==', value)
})
3Dos
  • 3,210
  • 3
  • 24
  • 37
1

CustomHook is one of the best ways to store a token as an object by using sessionStorage in React 17.0.1.

Follow these instructions:

  1. Implement sessionStorage get/set inside a custom function:

    export default function useToken() {
       const getToken = () => {
         const tokenString = sessionStorage.getItem('token');
         const userToken = JSON.parse(tokenString);
         return userToken?.token;
       };
    
       const [token, setToken] = useState(getToken());
    
       const saveToken = (userToken) => {
         sessionStorage.setItem('token', JSON.stringify(userToken));
         setToken(userToken.token);
       };
    
    
       return {
         setToken: saveToken,
         token,
       };
     }
    
  2. This function can be imported and used as a hook in other components like:

     import useToken from './useToken';
    
     const { token, setToken} = useToken(); // call CustomHook
    
     const handleSubmit = async (event) => {
         event.preventDefault();
         // call functionAPI
         const token = await loginUser({
           username,
           password,
         });
         setToken(token); // AUTOMATICALLY token will be stored to sessionStorage of browser
       };
    
Rigers Leka
  • 431
  • 5
  • 5