Salvar objetos Javascript na sessão

152

SessionStorage e LocalStorage permitem salvar pares de chave / valor em um navegador da web. O valor deve ser uma sequência e salvar objetos js não é trivial.

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

Atualmente, você pode evitar essa limitação serializando objetos para JSON e desserializando-os para recuperar os objetos. Mas a API de armazenamento sempre passa pelos métodos setIteme getItem.

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

Posso evitar essa limitação?

Eu só quero executar algo como isto:

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

Eu tentei os métodos defineGettere defineSetterpara interceptar as chamadas, mas é um trabalho tedioso, porque tenho que definir todas as propriedades e meu objetivo é não conhecer as propriedades futuras.

Ferran Basora
fonte
1
Eu já pensei nisso. Suponho que muitas pessoas tenham. Mas não acho que os métodos getter e setter sejam um fardo demais. BTW; você pode serializar e analisar com JavaScript e o MS finalmente suporta os mesmos objetos padrão que todos os outros. Os dias de necessidade de pacotes como JSON e jQuery estão chegando rapidamente ao fim.
Roger F. Gay
1
Acho que não vejo a limitação. Pode parecer um exagero usar JSON.stringify e JSON.parse se você tiver apenas objetos triviais, mas se você tiver objetos de dados de bom tamanho, esses dois métodos farão muito trabalho para você.
Robusto
5
"Posso evitar essa limitação?" parece ser uma pergunta #
19614 sonicblis
1
Bem, limitação ou não, essa pergunta me ajudou a resolver um problema, então, obrigado.
Matt West

Respostas:

19

Você pode usar os acessadores fornecidos pela API de armazenamento na Web ou escrever um wrapper / adaptador. Do problema declarado com defineGetter / defineSetter, parece que escrever um wrapper / adaptador é muito trabalhoso para você.

Sinceramente, não sei o que lhe dizer. Talvez você possa reavaliar sua opinião sobre o que é uma "limitação ridícula". A API de armazenamento na Web é exatamente o que deveria ser, um armazenamento de chave / valor.

Ryan Olds
fonte
8
Desculpe se usei uma palavra inadequada com 'ridículo'. Substitua por "poderia ser tão interessante". Penso que o webStorage é uma das melhorias mais empolgantes da nova web. Mas salve apenas as strings no mapa-chave do valor que eu acho que é uma limitação. Parece uma sequela de biscoitos. Eu sei que o Storage é uma especificação não apenas para a linguagem Javascript, mas serializar objetos pode ser uma melhoria interessante. O que você acha?
Ferran Basora
2
Se o JSON não for suficiente, você sempre poderá escrever seus próprios métodos de serialização de objetos.
Ryan Olds
110

Você não poderia 'restringir' o seu objeto ... depois usar sessionStorage.setItem()para armazenar essa representação de string do seu objeto ... quando precisar sessionStorage.getItem()e depois usá $.parseJSON()-lo para recuperá-lo?

Exemplo de trabalho http://jsfiddle.net/pKXMa/

afreeland
fonte
Isso funciona para mim. Eu recebo um objeto Json de trabalho depois de chamar $ .parseJSON ()
Olafur Tryggvason
Alguns sistemas, como a autenticação da API da Web, retornam objetos na forma de Objeto {propertyOneWithoutQuotes: "<value1>", ... propertyNWithoutQuotes: "<valueN>"} que precisam passar por "stringify". Se houver várias fontes, pode ser melhor usar o stringify para padronizar os dados.
Jelgab
Esta é uma resposta muito boa. É bom usar JSON.stringify () para serializar objetos e armazenar em sessionStorage. Em seguida, use $ .parseJSON () para desserializar a string para obter o objeto.
amigos estão dizendo sobre theatre
102

A solução é restringir o objeto antes de chamar setItem no sessionStorage.

var user = {'name':'John'};
sessionStorage.setItem('user', JSON.stringify(user));
var obj = JSON.parse(sessionStorage.user);
Ron
fonte
Obrigado por não vincular a solução
Luc-Olsthoorn
12

Esta é uma solução dinâmica que funciona com todos os tipos de valores, incluindo objetos:

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

Então :

const session = new Session();

session.set('name', {first: 'Ahmed', last : 'Toumi'});
session.get('name');
Abdennour TOUMI
fonte
5

Caso de uso:

 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
fonte
4
Eu pensei que uma das melhores práticas em javascript era não protótipo de objetos que você não possui. Usar Storage.prototype.setObj parece uma má ideia.
britztopher
3
apenas adicionando o obrigatório .. certifique-se de não adicionar este código protótipo - e confiar nele exclusivamente - sem primeiro verificar se o navegador suporta armazenamento:if (typeof (Storage) !== "undefined"){ /* browser supports it */ }
JoeBrockhaus
4

O armazenamento da sessão não pode suportar um objeto arbitrário porque pode conter literais de função (fechamentos de leitura) que não podem ser reconstruídos após o recarregamento de uma página.

Igor Urisman
fonte
3
    var user = {'name':'John'};
    sessionStorage['user'] = JSON.stringify(user);
    console.log(sessionStorage['user']);
Jijo Paulose
fonte
2

Você também pode usar a biblioteca da loja que executa para você com capacidade de navegação cruzada.

exemplo:

// 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
fonte
0

Você pode criar 2 métodos de wrapper para salvar e recuperar objetos do armazenamento da sessão.

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-o assim: - Obtenha um objeto, modifique alguns dados e salve de volta.

var obj = getSession();

obj.newProperty = "Prod"

saveSession(obj);
JerryGoyal
fonte