Empaquetar y descomprimir arquitectura de objetos complejos con JSON

He estado investigando el nuevo almacenamiento local de HTML 5 y parece bastante bueno hasta ahora. Decidí usar JSON para serializar mis objetos en cadenas y volver a analizarlos en objetos, lo que suena muy bien. Sin embargo, es más fácil decirlo que hacerlo. He descubierto que no puedes simplemente JSON.stringify() un objeto y espero que esté bien embalado para ti, pero no puedo entender qué tengo que hacer en su lugar.

Sin embargo, eso no es todo: mi objeto contiene dos matrices, cada una de las cuales contiene otro tipo de objeto y una de ellas es multidimensional. Así es como se ve mi arquitectura de objetos bastante compleja e interdependiente:

function Vector2(x, y) {
    this.x = x;
    this.y = y;
}

function Bar(ID, position) {
    this.id = id;
    this.position = position;
}

function Goo(state, position) {
    this.on = state;
    this.position = position;
}

function Foo(name, size) {
    this.name = name;
    this.size = size;
    this.bars = new Array(width)
    this.goos = new Array(10);

    this.Initialize();
}

Foo.prototype.Initialize() {
    for(var x = 0;x<this.size.x;x++) {
            this.bars[x] = new Array(this.size.y);

        for(var y=0;y<this.size.y;y++) {
            this.bars[x][y] = new Bar(x + y, new Vector2(x, y));
        }
    }

    for(var i = 0;i<this.goos.length;i++) {
        this.goos[i] = new Goo(on, new Vector2(i, i/2 + 1));
    }
}

Cada uno de esos objetos también tiene muchas funciones adicionales, cada una agregada usando el mismo método de prototipo que usé para agregar el método a Foo. Como dije, complejo. Mi pregunta es, ¿cómo serializo todo esto? ¿Realmente necesito agregar? toJSON() funciones para cada objeto?

Finalmente, una vez que haya empacado todo esto y lo haya guardado en localstorage, Sé cómo recuperarlo, pero no tengo ni idea de cómo descomprimirlo con JSON. Sin embargo, ese es otro asunto para otro momento, y sospecho que podría ser un poco más fácil de resolver por mi cuenta una vez que aprenda a empacar todo.

Nota: normalmente no sería una pregunta potencialmente tan amplia, pero realmente no pude encontrar nada aquí en SO o con mi (ciertamente débil) Google-fu que realmente aborde el problema, y ​​no sé cómo romper esto pregunta más abajo.

preguntado el 10 de marzo de 12 a las 02:03

4 Respuestas

Por lo general, no solo serializa estructuras de datos complejas en javascript porque la serialización normal no maneja múltiples diferencias, todas tienen referencias al mismo objeto, no pueden manejar referencias circulares, etc.

En cambio, lo que recomendaría es que averigüe cuál es el estado real de su aplicación. No toda la estructura del objeto instanciado, sino cuál es la cantidad mínima de información que realmente se necesita para reconstruir el estado de sus datos. Luego, una vez que lo haya descubierto (solo deben ser datos, no objetos reales), puede crear funciones o métodos para obtener esos datos de sus estructuras de datos o crear una nueva estructura de datos a partir de los datos.

Al mirar su código, el estado real de un Foo El objeto es una matriz bidimensional de Bar objetos y una matriz unidimensional de Goo objetos y un name y un size. La Bar solo tiene un x, y y id. Un Goo solo tiene un state y un x y un y. Ese sería un estado bastante fácil para escribir un método Foo para generar y un método Foo para aceptar ese estado del almacenamiento guardado.

respondido 10 mar '12, 02:03

Entonces, ¿realmente no serializaría los objetos, solo las cosas que necesito para reconstruirlos? Eso suena muy prometedor y, lo admito, más realista que solo serializar todo ... :) - Elliot Bonneville

@ElliotBonneville - sí. Hay lenguajes que le permiten serializar relaciones de objetos complicadas, pero javascript no es uno de esos. Guarde sus datos y podrá reconstruir los objetos a partir de los datos. Esto también tiene la ventaja de que solo está guardando los datos reales, por lo que el formato de guardado no está estrechamente relacionado con su esquema de implementación. Puede rediseñar el código y seguir admitiendo el mismo formato de datos guardados. Yo diría que el mejor formato de datos es 100% independiente de su implementación real, por lo que la implementación puede cambiar libremente. - amigo00

Suena como el curso de acción correcto a seguir. Acepto tu respuesta. ¡Gracias! - Elliot Bonneville

Hmm, el viaje se está volviendo un poco accidentado. Parece que no puedo stringify una serie de objetos. Bueno, puedo, pero si lo hago, pierdo todo menos la primera variable en cada objeto de la matriz. ¿Alguna idea de por qué? - Elliot Bonneville

Me parece que puede simplemente llamar a JSON.stringify en el objeto Foo para crear los datos. Luego, cuando lea esos datos, tendrá que asignar cada dato a un nuevo objeto Foo. Ver este jsFiddle para el ejemplo de stringify. Para su información, tuve que corregir muchos errores de codificación en el código de su pregunta para que se ejecutara. - amigo00

Agregar las funciones toJSON y fromJSON es probablemente la forma correcta de hacerlo. Solo debería guardar los datos únicos reales para cualquier objeto dado como JSON, no sería una buena idea serializar todo el objeto instanciado por varias razones importantes, la # 1 es que simplemente es innecesario. Además, piense en el caso en el que agrega o modifica funciones para uno de sus objetos en un futuro cercano: los clientes que habían almacenado sus propios objetos serializados nunca recibirán sus actualizaciones. El camino a seguir es simplemente almacenar los datos de instancia únicos y tener funciones para convertir esos datos en un objeto real (usando su definición más reciente).

respondido 10 mar '12, 02:03

Puede empaquetar funciones en cadenas:

var a = function() {return "a"};
a.toString()

// And also:

function b() {return "b"};
b.toString();

Entonces, a partir de ahí, puede piratear la fuente JSON (por Douglas Crockford) e incluir soporte para funciones. O algo.

respondido 10 mar '12, 02:03

Espero no llegar demasiado tarde aquí, pero acabo de encontrar el mismo problema.

Quería conservar un objeto de promesa (devuelto desde una llamada JQuery AJAX) al almacenamiento local.

Afortunadamente, me encontré con una pequeña biblioteca de JavaScript llamada Stash (http://rezitech.github.io/stash/). Hace posible tanto la serialización de objetos Javascript complejos en cadenas como el análisis de una cadena en un objeto Javascript.

Lo mejor es que no tiene que realizar explícitamente la serialización / análisis porque los tipos de datos se reconocen y transforman automáticamente cuando desea conservar / recuperar un objeto hacia / desde el almacenamiento local.

Aquí hay una prueba rápida que arrojó un resultado positivo.

// the api endpoint

var url = "www.api-host.com/api/bla/blub";

// create json call returning promise object

var promise = $.getJSON(url);

// persist promise object in local storage using dash.js

var key = url;

stash.set(key, promise);

// retrieve promise object from local storage

var stashGet = stash.get(key);

// display in console

console.log(stashGet);

Saludos, Matthias

contestado el 03 de mayo de 14 a las 18:05

Esta solución no resuelve su problema de serialización. - José Van Riper

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.