2010-08-31 52 views
30

Necesito serializar y deserializar objetos Javascript para almacenarlos en una base de datos.¿Cómo serializar y deserializar objetos Javascript?

Tenga en cuenta que estos objetos contienen funciones, por lo que no puedo almacenarlos como JSON, por lo que no puedo usar json2.js.

¿Cuál es el estado del arte en [de] serialización de objetos javascript (en javascript por supuesto).

Gracias, Stewart

+1

Por qué no puedes usar JSON? – Zoidberg

+1

Si un objeto javascript contiene funciones (es decir, métodos), entonces no hay forma de codificar esos en JSON. JSON solo maneja objetos JS con datos puros (hashes, arrays y tipos primitivos). –

+0

Específicamente: necesito almacenar un objeto DirectionsResult desde la API de JavaScript de Google Maps. DirectionsResult contiene LatLng * objects * que tienen funciones que no maneja JSON: http://code.google.com/apis/maps/documentation/javascript/reference.html#LatLng –

Respuesta

26

En general, no hay manera (en un navegador) de serializar los objetos con las funciones asociadas, ya que cada función tiene una referencia a su alcance exterior. Si la función hace referencia a cualquiera de esas variables, ya no existirán cuando la deserialice.

Lo que me TO es utilizar el built-in (o json2.js) JSON.stringify y JSON.parse funciones con los parámetros replacer y reviver. Aquí está un ejemplo parcial de cómo funcionaría:

JSON.stringify(yourObject, function(name, value) { 
    if (value instanceof LatLng) { // Could also check the name if you want 
     return 'LatLng(' + value.lat() + ',' + value.lng() + ')'; 
    } 
    else if (...) { 
     // Some other type that needs custom serialization 
    } 
    else { 
     return value; 
    } 
}); 

JSON.parse(jsonString, function(name, value) { 
    if (/^LatLng\(/.test(value)) { // Checking the name would be safer 
     var match = /LatLng\(([^,]+),([^,]+)\)/.exec(value); 
     return new LatLng(match[1], match[2]); 
    } 
    else if (...) { 
     ... 
    } 
    else { 
     return value; 
    } 
}); 

Se puede utilizar cualquier formato de serialización que desea en sus tipos personalizados. El formato "LatLng (latitud, longitud)" es solo una forma de hacerlo. Incluso podría devolver un objeto javascript que se pueda serializar a JSON de forma nativa.

+0

Interesante. Leí los documentos json2.js ("Los valores que no tienen una representación en JSON (como las funciones y los indefinidos) están excluidos.") Y asumí que las funciones sustituto/reanimador no se invocan en las funciones. ¿Este código realmente ha escrito y usado? –

+0

@Stewart: la idea es que evite tener que serializar las funciones mediante la reconstrucción de los objetos cuando los deserialice. El constructor 'LatLng' agregará las funciones nuevamente para usted. Sin embargo, el sustituto funcionará en las funciones, por lo que si realmente lo desea, podría intentar convertir la función en una cadena. Solo tenga en cuenta que no funcionará en todos los casos. –

7

uso gserializer:

http://www.onegeek.com.au/articles/programming/javascript-serialization.php

el código en Google:

http://code.google.com/p/gserializer/

GSerializer es una biblioteca de JavaScript a serializar/deserializar javascript objetos ay desde cadenas, para persistencia en say, a Cookie. A diferencia de muchas otras implementaciones, GSerializer también puede serializar funciones y notación no JSON.

+0

Me di cuenta de eso antes, pero no estaba seguro sobre la madurez del proyecto. ¿Lo has usado personalmente? –

+3

Parece que no funcionará: Gserializer TODO dice: "Implementar parámetros de paso en funciones serializadas (actualmente solo admite funciones sin argumento)", y los objetos que tengo que serializar contienen funciones con argumentos (función toUrlValue en objeto LatLng : http://code.google.com/apis/maps/documentation/javascript/reference.html#LatLng). ¡Gracias de cualquier manera! –

+0

lo siento 2, espero que terminen este proyecto –

10

No desea serializar la lógica como funciones.

Si tiene que actualizar sus funciones de lógica/js en el futuro, no (siempre) desea que la lógica anterior se cargue de nuevo con los datos necesarios. Tener cuidado.

1

En Node.js, también está el JASON package.

Aquí está el ejemplo:

var JASON = require("JASON"); 

str = JASON.stringify(obj); 
obj = JASON.parse(str); 

instalar el paquete por: npm install JASON.

0

No serializaría las funciones de JS por razones de seguridad. A través de una API pública, todo tipo de cosas desagradables podrían enviarse a la base de datos. En cuanto a la deserialización, tengo un enfoque diferente. Estoy mezclando objetos de modelo definidos en el lado del cliente con los datos provenientes de JSON. Tengo una pequeña herramienta para hacer eso, échale un vistazo a GitHub al khayll/jsonmix.

JsonMix proporciona un tipo de deserialización de JSON en JavaScript Objetos completos con funciones.

Se vería como algo:

//model definition (just an example) 

var LatLng = function() {} 
LatLng.prototype.getMapTypeId = function() { 
    return this.mapTypeId; 
} 

//deserializing done like this 
var result = JSMix(jsonString).withObject(LatLng.prototype, "latLngs").build(); 

//all items in the latLngs collection have the functions coming from the model 
console.log(result.latLngs[5].getMapTypeId()); 
+1

¿Puede aclarar por qué ** las funciones de JavaScript ** de serialización podrían, bajo cualquier circunstancia, ser un riesgo de seguridad? –

+0

si tiene una API pública, que acepta un objeto javascript serializado, incluida la funcionalidad, y esto se utiliza en una aplicación web. luego se puede enviar código malicioso a su servidor. Supongamos que también lee estos objetos en algún lugar de su aplicación web y los utiliza. Ahora bien, si alguien anula la función toString() en ese objeto, y la usa en su código, entonces alguien podría alterar la funcionalidad prevista de la aplicación web. Entonces, mientras lo descargaba desde una url segura, ya no se puede confiar en la funcionalidad. – fishgen

+1

Por supuesto. Pero es la aceptación por parte del servidor y la posterior deserialización y uso del código el riesgo. Serializarse a sí mismo no es peligroso. –

1

Si está utilizando versiones ES6 de nodo, puede comprobar fuera de un pequeño paquete que escribí llamado JSOFF. Es el formato de función de objeto de JavaScript; un reemplazo directo para JSON que maneja funciones.

Es super pequeño y simple, por lo que Babeljs o Browserify pueden ser tus amigos.

Instalar a través de: npm install jsoff o yarn add jsoff.

Aquí está el ejemplo de cómo crear un objeto con funciones:

const JSOFF = require('jsoff'); 

var obj = { 
    abc: 123, 
    def: function (a,b) { return a * 2 + b * 3; }, 
    ghi: a => { return a * 2 }, 
    jkl: (a,b) => { return ((d,e) => { return a*d + b*e })(2,4) } 
}; 

var str = JSOFF.stringify(obj); 
// str is now: 
// '{"abc":123,"def":"function (a,b) { return a * 2 + b * 3; }","ghi":"a => { return a * 2 }","jkl":"(a,b) => { return ((d,e) => { return a*d + b*e })(2,4) }"}'); 
}); 

var clone = JSOFF.parse(str); 
clone.def(10,5) // 35 
clone.ghi(5)  // 10 
clone.jkl(10,20) // 100 
Cuestiones relacionadas