Objektu glabāšana HTML5 localStorage

Vēlos saglabāt JavaScript objektu HTML5 localStorage, taču mans objekts tiek pārveidots par virkni.

Izmantojot localStorage, es varu saglabāt un izgūt primitīvos JavaScript tipus un masīvus, bet objekti, šķiet, nedarbojas. Vai tas būtu jādara?

Lūk, mans kods:

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);

Konsoles izvads ir šāds

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

Man šķiet, ka setItem metode pārvērš ievades datus virknē pirms to saglabāšanas.

Es redzu šādu uzvedību pārlūkprogrammās Safari, Chrome un Firefox, tāpēc pieņemu, ka tā ir mana nepareiza HTML5 Web Storage specifikācijas izpratne, nevis pārlūkprogrammai raksturīga kļūda vai ierobežojums.

Esmu mēģinājis saprast http://www.w3.org/TR/html5/infrastructure.html aprakstīto strukturētā klona algoritmu. Es līdz galam nesaprotu, kas tur teikts, bet varbūt mana problēma ir saistīta ar to, ka mana objekta īpašības nav uzskaitāmas (????).

Vai ir kāds viegls risinājums?


Atjauninājums: W3C galu galā mainīja savas domas par strukturēto klonu specifikāciju un nolēma mainīt specifikāciju, lai tā atbilstu implementācijām. Skatīt https://www.w3.org/Bugs/Public/show_bug.cgi?id=12111. Tāpēc šis jautājums vairs nav 100% aktuāls, bet atbildes joprojām var interesēt.

Risinājums

Aplūkojot Apple, Mozilla un atkal Mozilla dokumentāciju, šķiet, ka funkcionalitāte ir ierobežota, lai apstrādātu tikai virknes atslēgu/vērtību pārus.

To var apiet, stringify savu objektu pirms saglabāšanas un vēlāk, to iegūstot, analizēt:

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));
Komentāri (5)

Neliels uzlabojums variants:

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);
}

Sakarā ar īssavienojuma izvērtēšanu getObject() nekavējoties *atgriež null, ja key nav krātuvē. Tā arī neizmet SyntaxError izņēmumu, ja value ir "" (tukša virkne; JSON.parse() to nevar apstrādāt).

Komentāri (10)

Jums varētu būt noderīgi paplašināt krātuves objektu ar šīm ērtajām metodēm:

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

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

Šādā veidā jūs iegūsiet funkcionalitāti, ko jūs patiešām vēlējāties, lai gan API apakšā tiek atbalstītas tikai virknes.

Komentāri (3)