Objecten opslaan in HTML5 localStorage

Ik'wil een JavaScript object opslaan in HTML5 localStorage, maar mijn object wordt blijkbaar geconverteerd naar een string.

Ik kan primitieve JavaScript-types en arrays opslaan en opvragen met localStorage, maar objecten lijken niet te werken. Zou dat moeten?

Hier's mijn 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);

De console uitvoer is

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

Het lijkt mij dat de setItem methode de invoer omzet naar een string voordat het wordt opgeslagen.

Ik zie dit gedrag in Safari, Chrome en Firefox, dus ik neem aan dat het mijn misverstand van de HTML5 Web Storage spec is, en niet een browser-specifieke bug of beperking.

Ik'heb geprobeerd om zin te geven aan het gestructureerde kloon algoritme beschreven in http://www.w3.org/TR/html5/infrastructure.html. Ik begrijp niet helemaal wat het zegt, maar misschien heeft mijn probleem te maken met het feit dat de eigenschappen van mijn object niet opsommbaar zijn (???)

Is er een gemakkelijke workaround?


Update: Het W3C is uiteindelijk van gedachten veranderd over de structured-clone specificatie, en heeft besloten om de spec aan te passen aan de implementaties. Zie https://www.w3.org/Bugs/Public/show_bug.cgi?id=12111. Deze vraag is dus niet langer 100% geldig, maar de antwoorden kunnen nog steeds interessant zijn.

Oplossing

Kijkend naar de Apple, Mozilla en Mozilla opnieuw documentatie, lijkt de functionaliteit beperkt te zijn tot het afhandelen van alleen string key/value paren.

Een workaround kan zijn om je object te stringify voordat je het opslaat, en het later te parsen als je het ophaalt:

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));
Commentaren (5)

Een kleine verbetering ten opzichte van een 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);
}

Vanwege kortsluiting evaluatie, getObject() zal onmiddellijk null teruggeven als key niet in Storage zit. Het zal ook geen SyntaxError exception gooien als value "" is (de lege string; JSON.parse() kan daar niet mee omgaan).

Commentaren (10)

Je zou het nuttig kunnen vinden om het Storage object uit te breiden met deze handige methodes:

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

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

Op deze manier krijg je de functionaliteit die je echt wilde, ook al ondersteunt de API daaronder alleen strings.

Commentaren (3)