Zapisz obiekty JavaScript w sessionStorage

152

SessionStorage i LocalStorage umożliwiają zapisywanie par klucz / wartość w przeglądarce internetowej. Wartość musi być łańcuchem, a save js obiektów nie jest trywialny.

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

Obecnie można uniknąć tego ograniczenia, serializując obiekty do formatu JSON, a następnie deserializując je w celu odzyskania obiektów. Ale interfejs API magazynu zawsze przechodzi przez metody setItemi getItem.

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

Czy mogę uniknąć tego ograniczenia?

Chcę tylko wykonać coś takiego:

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

Wypróbowałem metody defineGetteri defineSetterdo przechwytywania wywołań, ale jest to żmudna praca, ponieważ muszę zdefiniować wszystkie właściwości, a moim celem nie jest znajomość przyszłych właściwości.

Ferran Basora
źródło
1
Sam o tym myślałem. Przypuszczam, że wiele osób ma. Ale nie sądzę, aby metody getter i setter były zbyt dużym obciążeniem. BTW; możesz serializować i analizować za pomocą JavaScript, a MS w końcu obsługuje te same standardowe obiekty, co wszyscy inni. Dni, w których potrzebne były pakiety takie jak JSON i jQuery, szybko dobiegają końca.
Roger F. Gay
1
Chyba nie widzę ograniczenia. Używanie JSON.stringify i JSON.parse może wydawać się przesadą, jeśli masz tylko trywialne obiekty, ale jeśli masz nawet duże obiekty danych, te dwie metody wykonują dużo pracy.
Robusto
5
„Czy mogę uniknąć tego ograniczenia?” wydaje się być pytaniem
sonicblis
1
Cóż, ograniczenie czy nie, to pytanie pomogło mi rozwiązać problem, więc dziękuję.
Matt West

Odpowiedzi:

19

Możesz użyć metod dostępu udostępnianych przez interfejs API usługi Web Storage lub napisać opakowanie / adapter. Z twojego stwierdzonego problemu z defineGetter / defineSetter wynika, że ​​napisanie wrappera / adaptera to dla ciebie za dużo pracy.

Naprawdę nie wiem, co ci powiedzieć. Może mógłbyś zrewidować swoją opinię o tym, co jest „śmiesznym ograniczeniem”. Interfejs API usługi Web Storage jest tym, czym powinien być, magazynem kluczy / wartości.

Ryan Olds
źródło
8
Przepraszam, jeśli użyłem niewłaściwego słowa z „niedorzecznym”. Zastąp go słowami „mogłoby być tak interesujące”. Myślę, że magazyn webStorage jest jednym z najbardziej ekscytujących ulepszeń nowej sieci. Ale zapisuj tylko ciągi znaków w mapie klucza wartości. Myślę, że jest to ograniczenie. Wygląda na to, że jest to kontynuacja ciastek. Wiem, że Storage to specyfikacja nie tylko dla języka JavaScript, ale serializacja obiektów może być interesującym ulepszeniem. Co myślisz?
Ferran Basora
2
Jeśli JSON nie wystarczy, zawsze możesz napisać własne metody serializacji obiektów.
Ryan Olds
110

Czy nie mógłbyś 'stringify' swojego obiektu ... potem użyć sessionStorage.setItem()do przechowywania reprezentacji ciągu twojego obiektu ... potem, kiedy tego potrzebujesz, sessionStorage.getItem()a następnie użyć, $.parseJSON()aby go odzyskać?

Przykład roboczy http://jsfiddle.net/pKXMa/

afreeland
źródło
To działa dla mnie. Otrzymuję działający obiekt Json po wywołaniu $ .parseJSON ()
Olafur Tryggvason
Niektóre systemy, takie jak uwierzytelnianie Web Api zwracają obiekty w postaci Object {propertyOneWithoutQuotes: "<value1>", ... propertyNWithoutQuotes: "<valueN>"}, które muszą przejść przez "stringify". Jeśli istnieje wiele źródeł, do standaryzacji danych lepiej byłoby użyć stringify.
Jelgab
To bardzo dobra odpowiedź. Do serializacji obiektu i przechowywania w sessionStorage dobrze jest użyć JSON.stringify (). Następnie używa $ .parseJSON () do deserializacji ciągu w celu uzyskania obiektu.
Thomas.Benz
102

Rozwiązaniem jest określenie ciągu obiektu przed wywołaniem setItem w sessionStorage.

var user = {'name':'John'};
sessionStorage.setItem('user', JSON.stringify(user));
var obj = JSON.parse(sessionStorage.user);
Ron
źródło
Dziękuję, że nie łączysz rozwiązania
Luc-Olsthoorn
12

Jest to dynamiczne rozwiązanie, które działa ze wszystkimi typami wartości, w tym obiektami:

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

Następnie :

const session = new Session();

session.set('name', {first: 'Ahmed', last : 'Toumi'});
session.get('name');
Abdennour TOUMI
źródło
5

Przypadek użycia:

 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))
    };
Abdennour TOUMI
źródło
4
Pomyślałem, że jedną z najlepszych praktyk w javascript jest powstrzymanie się od tworzenia prototypów obiektów, których nie jesteś właścicielem. Używanie Storage.prototype.setObj wydaje się złym pomysłem.
britztopher
3
po prostu dodając obowiązkowe .. upewnij się, że nie dodajesz tego prototypowego kodu - i polegaj wyłącznie na nim - bez uprzedniego sprawdzenia, czy przeglądarka go obsługuje Przechowywanie:if (typeof (Storage) !== "undefined"){ /* browser supports it */ }
JoeBrockhaus Kwietnia
4

Magazyn sesji nie może obsługiwać dowolnego obiektu, ponieważ może zawierać literały funkcyjne (zamknięcia odczytu), których nie można odtworzyć po przeładowaniu strony.

Igor Urisman
źródło
3
    var user = {'name':'John'};
    sessionStorage['user'] = JSON.stringify(user);
    console.log(sessionStorage['user']);
Jijo Paulose
źródło
2

Możesz także skorzystać z biblioteki sklepu, która wykonuje to za Ciebie z możliwością obsługi różnych przeglądarek.

przykład:

// 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
źródło
0

Możesz utworzyć dwie metody opakowujące do zapisywania i pobierania obiektów z pamięci sesji.

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

Użyj tego w ten sposób: - Pobierz obiekt, zmodyfikuj niektóre dane i zapisz z powrotem.

var obj = getSession();

obj.newProperty = "Prod"

saveSession(obj);
JerryGoyal
źródło