Guardar objetos Javascript en sessionStorage

152

SessionStorage y LocalStorage permite guardar pares clave / valor en un navegador web. El valor debe ser una cadena y guardar objetos js no es trivial.

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

Hoy en día, puede evitar esta limitación al serializar objetos en JSON y luego deserializarlos para recuperar los objetos. Pero la API de almacenamiento siempre pasa por los métodos setItemy getItem.

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

¿Puedo evitar esta limitación?

Solo quiero ejecutar algo como esto:

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

He intentado los métodos defineGettery defineSetterpara interceptar las llamadas, pero es un trabajo tedioso, porque tengo que definir todas las propiedades y mi objetivo es no conocer las propiedades futuras.

Ferran Basora
fuente
1
He pensado en eso yo mismo. Supongo que mucha gente tiene. Pero no creo que los métodos getter y setter sean una gran carga. Por cierto; puede serializar y analizar con JavaScript y MS finalmente admite los mismos objetos estándar que todos los demás. Los días de necesidad de paquetes como JSON y jQuery están llegando rápidamente a su fin.
Roger F. Gay
1
Supongo que no veo la limitación. Puede parecer excesivo usar JSON.stringify y JSON.parse si solo tiene objetos triviales, pero si tiene incluso objetos de datos de buen tamaño, estos dos métodos están haciendo un gran trabajo por usted.
Robusto
55
"¿Puedo evitar esta limitación?" parece una pregunta
sonicblis
1
Bueno, limitación o no, esta pregunta me ayudó a resolver un problema, así que gracias.
Matt West

Respuestas:

19

Puede usar los accesores proporcionados por la API de almacenamiento web o puede escribir un contenedor / adaptador. Según su problema declarado con defineGetter / defineSetter, parece que escribir un contenedor / adaptador es demasiado trabajo para usted.

Sinceramente, no sé qué decirte. Tal vez podría reevaluar su opinión sobre lo que es una "limitación ridícula". La API de almacenamiento web es justo lo que se supone que es, un almacén de clave / valor.

Ryan Olds
fuente
8
Lo siento si he usado una palabra inapropiada con 'ridículo'. Reemplácelo con 'podría ser tan interesante'. Creo que webStorage es una de las mejoras más emocionantes de la nueva web. Pero guardar solo cadenas en el mapa de teclas de valor, creo que es una limitación. Parece una secuela de cookies. Sé que el Almacenamiento es una especificación no solo para el lenguaje Javascript, sino que serializar objetos podría ser una mejora interesante. ¿Qué piensas?
Ferran Basora
2
Si JSON no es suficiente, siempre puede escribir sus propios métodos de serialización de objetos.
Ryan Olds
110

¿No podría 'encadenar' su objeto ... luego usarlo sessionStorage.setItem()para almacenar esa representación de cadena de su objeto ... luego cuando lo necesite sessionStorage.getItem()y luego usar $.parseJSON()para recuperarlo?

Ejemplo de trabajo http://jsfiddle.net/pKXMa/

afreeland
fuente
Esto funciona para mi. Obtengo un objeto Json que funciona después de llamar a $ .parseJSON ()
Olafur Tryggvason el
Algunos sistemas, como la autenticación Web Api, devuelven objetos en forma de Object {propertyOneWithoutQuotes: "<value1>", ... propertyNWithoutQuotes: "<valueN>"} que deben pasar por "stringify". Si hay varias fuentes, podría ser mejor usar stringify para estandarizar los datos.
Jelgab
Esta es una muy buena respuesta. Es bueno usar JSON.stringify () para serializar objetos y almacenarlos en sessionStorage. Luego, usa $ .parseJSON () para deserializar la cadena para obtener el objeto.
Thomas.Benz
102

La solución es stringificar el objeto antes de llamar a setItem en sessionStorage.

var user = {'name':'John'};
sessionStorage.setItem('user', JSON.stringify(user));
var obj = JSON.parse(sessionStorage.user);
Ron
fuente
Gracias por no vincular la solución
Luc-Olsthoorn
12

Esta es una solución dinámica que funciona con todos los tipos de valores, incluidos los 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;
    }
  }
}

Luego :

const session = new Session();

session.set('name', {first: 'Ahmed', last : 'Toumi'});
session.get('name');
Abdennour TOUMI
fuente
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
fuente
44
Pensé que una de las mejores prácticas en JavaScript era no crear prototipos de objetos que no son de su propiedad. Usar Storage.prototype.setObj parece una mala idea.
britztopher
3
simplemente agregando lo obligatorio ... asegúrese de no agregar este código prototipo, y confíe exclusivamente en él, sin verificar primero si el navegador lo admite Almacenamiento:if (typeof (Storage) !== "undefined"){ /* browser supports it */ }
JoeBrockhaus
4

El almacenamiento de la sesión no puede admitir un objeto arbitrario porque puede contener literales de función (cierres de lectura) que no se pueden reconstruir después de una recarga de página.

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

También puede usar la biblioteca de la tienda que lo realiza para usted con la capacidad de crossbrowser.

ejemplo:

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

Puede crear 2 métodos de contenedor para guardar y recuperar objetos del almacenamiento de la sesión.

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

Úselo así: - Obtenga un objeto, modifique algunos datos y guarde de nuevo.

var obj = getSession();

obj.newProperty = "Prod"

saveSession(obj);
JerryGoyal
fuente