46

No jQuery.

I want to store an object or array in a cookie.

The object should be usable after page refresh.

How do I do that with pure JavaScript? I read many posts, but do not know how to serialize appropriately.


EDIT: Code:

var instances = {};
...
instances[strInstanceId] = { container: oContainer };
...
instances[strInstanceId].plugin = oPlugin;
...
JSON.stringify(instances); 
// throws error 'TypeError: Converting circular structure to JSON'
  1. How do I serialize instances?

  2. How do I maintain functionality, but change structure of instance to be able to serialize with stringify?

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Shlomo
  • 3,880
  • 8
  • 50
  • 82
  • 5
    [`JSON.stringify()`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/JSON/stringify) it. – Matt Jul 05 '12 at 12:40
  • convert object to json and store it in cookie. – Muthu Kumaran Jul 05 '12 at 12:40
  • `stringify` does not work. I get `TypeError: Converting circular structure to JSON` my code is: `var instances = {}; instances[strInstanceId].plugin = oPlugin; ...` – Shlomo Jul 05 '12 at 14:00

5 Answers5

79

Try that one to write

function bake_cookie(name, value) {
  var cookie = [name, '=', JSON.stringify(value), '; domain=.', window.location.host.toString(), '; path=/;'].join('');
  document.cookie = cookie;
}

To read it take:

function read_cookie(name) {
 var result = document.cookie.match(new RegExp(name + '=([^;]+)'));
 result && (result = JSON.parse(result[1]));
 return result;
}

To delete it take:

function delete_cookie(name) {
  document.cookie = [name, '=; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; domain=.', window.location.host.toString()].join('');
}

To serialize complex objects / instances, why not write a data dump function in your instance:

function userConstructor(name, street, city) {
   // ... your code
   this.dumpData = function() {
     return {
        'userConstructorUser': {
            name: this.name,
            street: this.street,
            city: this.city
         }
       }
    }

Then you dump the data, stringify it, write it to the cookie, and next time you want to use it just go:

  var mydata = JSON.parse(read_cookie('myinstances'));
  new userConstructor(mydata.name, mydata.street, mydata.city);
Beat Richartz
  • 9,474
  • 1
  • 33
  • 50
  • Thanks Ill go with that if I get `stringify` to work. Can you check my code problem? – Shlomo Jul 05 '12 at 14:39
  • JSON cannot serialize whole instances, but you can serialize any relevant data you may want from these instances, and reinitialize them with this saved data. For example, you have an instance where name = 'John Doe', you could write a function on that instance to return an object like {myinstance: {name: 'John Doe'}}, and then call the constructor again with this data. Other than that, you could try the GSerializer: http://www.onegeek.com.au/projects/javascript-serialization (good post on that) But I would recommend against that because Cookies are limited in size... – Beat Richartz Jul 05 '12 at 15:48
  • 1
    ... and a cookie too large can result in permanent site failure for the user without you noticing it because the Upstream header is too big. I edited my post so you can see what I mean by my comment above. – Beat Richartz Jul 05 '12 at 15:49
  • I do not understand your answer with your dump function. The variable `instances` holds 2 objects which lead to this error, one is a ExtJS and the other a DeftJS object. How can I serialize these? Could you explain it more please? – Shlomo Jul 06 '12 at 07:00
  • Every JS Instance typically has two types of data in it: [attributes](http://en.wikipedia.org/wiki/Attribute_(computer_science)) and [functions](http://en.wikipedia.org/wiki/Function_(computer_science)). What I meant to say by my comment was that it is useless to store the functions in your cookie, because these are normally not subject to change. You should extract the attributes and write them to a cookie, because storing instances of large instances (and my guess is that somehow stringified ExtJS and DeftJS instances would be huge) do not fit in a cookie (size limit is 4KB, essentialy)... – Beat Richartz Jul 06 '12 at 07:33
  • ...However, if ExtJS or DeftJS are extensible somehow, you could write a data extract function to extract the attributes, write them in a cookie and reinstantiate the objects with the stored data on page load. If there's no way to do that, maybe you can provide me with the target you want to achieve by storing instances, and maybe I could provide another way to do that. If browser choice is not an issue (for example, if you develop this for a company internal website and they could force a browser to be used), you could have a look at.... – Beat Richartz Jul 06 '12 at 07:38
  • [html5 browser storage](http://rickosborne.org/blog/2010/03/html5-in-browser-sql-database-storage/) To store larger sets of data and have a look at [this post](http://blog.maxaller.name/2011/01/javascript-serialization/) which essentially explains how to hack around that issue you're having with stringifying instances. – Beat Richartz Jul 06 '12 at 07:41
  • Ok thanks now I get it. Ill try to figure out what attr I need, I dont know yet. My target is to be achieve persistence of my ExtJs app after page refresh. There is ExtJs state cookie provider functionality, but for my instances object which holds multiple instances of the same app, I need to also store this. – Shlomo Jul 06 '12 at 09:01
  • It seems that commas are disallowed in cookie values as they might be interpreted as separators... https://developer.mozilla.org/en-US/docs/Web/API/document/cookie Would it not be a problem if I directly use `JSON.stringify()`, which might produce commas? – xji Aug 19 '18 at 13:38
  • Seems that using `encodeURLComponent` after `JSON.stringify` solves it. Then when reading the cookie one also needs to first decode it before running `JSON.parse` – xji Aug 19 '18 at 14:10
  • Shouldn't `read_cookie()` be `eat_cookie()`? – avisk Aug 07 '21 at 00:10
6

If you can serialize your object into its canonical string representation, and can unserialize it back into its object form from said string representation, then yes you can put it into a cookie.

Clément Andraud
  • 9,103
  • 25
  • 80
  • 158
6

Use either object's own .toString() method if it gives meaningful serialization or JSON.stringify(). Do note, however, that cookies are usually limited in length and won't be able to hold big amounts of data.

Oleg V. Volkov
  • 21,719
  • 4
  • 44
  • 68
6

A cookie adaptation class from : http://www.sitepoint.com/cookieless-javascript-session-variables/

All you need to do is to set and get variables you need to store in cookie.

Work with: int, string, array, list, Complex object

Exemple:

var toStore =  Session.get('toStore');

if (toStore == undefined)
    toStore = ['var','var','var','var'];
else
    console.log('Restored from cookies'+toStore);

Session.set('toStore', toStore);

Class:

// Cross reload saving
if (JSON && JSON.stringify && JSON.parse) var Session = Session || (function() {
// session store

var store = load();

function load()
{
    var name = "store";
    var result = document.cookie.match(new RegExp(name + '=([^;]+)'));

    if (result)
        return JSON.parse(result[1]);

    return {};
}

function Save() {
    var date = new Date();
    date.setHours(23,59,59,999);
    var expires = "expires=" + date.toGMTString();
    document.cookie = "store="+JSON.stringify(store)+"; "+expires;
};

// page unload event
if (window.addEventListener) window.addEventListener("unload", Save, false);
else if (window.attachEvent) window.attachEvent("onunload", Save);
else window.onunload = Save;

// public methods
return {

    // set a session variable
    set: function(name, value) {
        store[name] = value;
    },

    // get a session value
    get: function(name) {
        return (store[name] ? store[name] : undefined);
    },

    // clear session
    clear: function() { store = {}; }
};
})();
0

Elaborating on @Clément Andraud answer. You can JSON.stringify a JS object and store it as a cookie. Later you can access that cookie and convert it back to a JS object.

var a = new Date(Date.now() + 1000 * 60 * 60 * 24 * 2);//2 days

Object ={
    "utm_medium": "Medium",
    "utm_campaign": "Name of something",
    "utm_id": "Id",
    "utm_content": "content",
    "utm_source": "tlchatt.com"
}
document.cookie = 'CookeName=' + JSON.stringify(paramsObjectArray) +';  path=/; expires=' + a.toGMTString() + ';' 
Greggory Wiley
  • 660
  • 6
  • 16