Sé cómo analizar una cadena JSON y convertirla en un objeto JavaScript. Puede usar JSON.parse()
en navegadores modernos (e IE9 +).
Eso es genial, pero ¿cómo puedo tomar ese Objeto JavaScript y convertirlo en un Objeto JavaScript particular (es decir, con un cierto prototipo)?
Por ejemplo, suponga que tiene:
function Foo()
{
this.a = 3;
this.b = 2;
this.test = function() {return this.a*this.b;};
}
var fooObj = new Foo();
alert(fooObj.test() ); //Prints 6
var fooJSON = JSON.parse({"a":4, "b": 3});
//Something to convert fooJSON into a Foo Object
//....... (this is what I am missing)
alert(fooJSON.test() ); //Prints 12
Nuevamente, no me pregunto cómo convertir una cadena JSON en un objeto JavaScript genérico. Quiero saber cómo convertir una cadena JSON en un objeto "Foo". Es decir, mi Objeto ahora debería tener una función 'prueba' y propiedades 'a' y 'b'.
ACTUALIZACIÓN Después de investigar un poco, pensé en esto ...
Object.cast = function cast(rawObj, constructor)
{
var obj = new constructor();
for(var i in rawObj)
obj[i] = rawObj[i];
return obj;
}
var fooJSON = Object.cast({"a":4, "b": 3}, Foo);
¿Eso funcionará?
ACTUALIZACIÓN Mayo de 2017 : La forma "moderna" de hacerlo es a través de Object.assign
, pero esta función no está disponible en IE 11 o en navegadores Android anteriores.
Respuestas:
Las respuestas actuales contienen mucho código enrollado a mano o de biblioteca. Esto no es necesario.
Use
JSON.parse('{"a":1}')
para crear un objeto plano.Use una de las funciones estandarizadas para configurar el prototipo:
Object.assign(new Foo, { a: 1 })
Object.setPrototypeOf({ a: 1 }, Foo.prototype)
fuente
Object.setPrototypeOf(...)
. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…setPrototypeOf
son los descriptores de propiedad.Vea un ejemplo a continuación (este ejemplo usa el objeto JSON nativo). Mis cambios se comentan en CAPITALES:
fuente
for (var prop in obj) {if (obj.hasOwnProperty(prop)) {this[prop] = obj[prop];}}
for (var prop in obj) {if (this.hasOwnProperty(prop)) {this[prop] = obj[prop];}}
. Esto supone que espera que el servidor complete todas las propiedades, la OMI también debería lanzar si obj.hasOwnProperty () falla ...¿Desea agregar la funcionalidad de serialización / deserialización JSON, verdad? Entonces mira esto:
quieres lograr esto:
toJson () es un método normal.
fromJson () es un método estático.
implementación :
Uso :
Nota: Si lo desea, puede cambiar todas las definiciones de propiedades como
this.title
,this.author
, etc porvar title
,var author
, etc y añadir captadores a ellos para llevar a cabo la definición de UML.fuente
toJson()
método, independientemente de si tiene propiedades individuales codificadas o utiliza un para cada, necesitará agregar códigos de escape de barra invertida para algunos caracteres que podrían estar en cada propiedad de cadena. (El título de un libro podría tener comillas, por ejemplo)JSON.stringify()
lugar de escribirle a JSon (). No es necesario reinventar la rueda ahora que todos los navegadores modernos lo admiten.serializable = ['title', 'author', ...]
.JSON.stringify(serializable.reduce((obj, prop) => {...obj, [prop]: this[prop]}, {}))
Una publicación de blog que me pareció útil: comprender los prototipos de JavaScript
Puede meterse con la propiedad __proto__ del objeto.
Esto permite que fooJSON herede el prototipo de Foo.
Sin embargo, no creo que esto funcione en IE ... al menos por lo que he leído.
fuente
__proto__
ha quedado en desuso por mucho tiempo . Además, por razones de rendimiento, no se recomienda modificar la propiedad interna [[Prototipo]] de un objeto ya creado (mediante configuración__proto__
o por cualquier otro medio).[[prototype]]
y parece ser irrelevante en Chrome. En Firefox, llamar a nuevo es más lento que usar un prototipo, y Object.create es más rápido. Supongo que el problema con FF es que la primera prueba es más lenta que la última, solo importa el orden de ejecución. En Chrome todo funciona casi a la misma velocidad. Me refiero al acceso a la propiedad y la invocación de métodos. La creatina es más rápida con las nuevas, pero eso no es tan importante. ver: jsperf.com/prototype-change-test-8874874/1 y: jsperf.com/prototype-changed-method-callObject.setPrototypeOf(fooJSON, Foo.prototype)
lugar de configurarfooJSON.__proto__
... ¿verdad?¿Me falta algo en la pregunta o por qué nadie mencionó el
reviver
parámetroJSON.parse
desde 2011?Aquí hay un código simplista para la solución que funciona: https://jsfiddle.net/Ldr2utrr/
PD: Su pregunta es confusa: >> Eso es genial, pero ¿cómo puedo tomar ese Objeto JavaScript y convertirlo en un Objeto JavaScript particular (es decir, con un cierto prototipo)? contradice el título, donde pregunta sobre el análisis JSON, pero el párrafo citado pregunta sobre el reemplazo del prototipo de objeto de tiempo de ejecución JS.
fuente
Se podría usar un enfoque alternativo
Object.create
. Como primer argumento, pasa el prototipo, y para el segundo pasa un mapa de nombres de propiedades a los descriptores:fuente
Me gusta agregar un argumento opcional al constructor y llamar
Object.assign(this, obj)
, luego manejar cualquier propiedad que sea objeto o matriz de objetos en sí:fuente
En aras de la exhaustividad, aquí hay una línea simple con la que terminé (no tuve necesidad de verificar las propiedades no Foo):
fuente
Creé un paquete llamado json-dry . Admite referencias (circulares) y también instancias de clase.
Debe definir 2 nuevos métodos en su clase (
toDry
en el prototipo yunDry
como método estático), registrar la clase (Dry.registerClass
) y listo.fuente
Si bien, esto no es técnicamente lo que desea, si conoce de antemano el tipo de objeto que desea manejar, puede usar los métodos de llamada / aplicación del prototipo de su objeto conocido.
puedes cambiar esto
a esto
fuente
Combiné las soluciones que pude encontrar y las compilé en una genérica que puede analizar automáticamente un objeto personalizado y todos sus campos de forma recursiva para que pueda usar métodos prototipo después de la deserialización.
Una suposición es que definió un archivo especial que indica que es tipo en cada objeto que desea aplicar su tipo automáticamente (
this.__type
en el ejemplo).uso:
Función de asignación de tipo (funciona de forma recursiva para asignar tipos a cualquier objeto anidado; también itera a través de matrices para encontrar cualquier objeto adecuado):
fuente
La respuesta actualmente aceptada no estaba funcionando para mí. Necesita usar Object.assign () correctamente:
Normalmente crea objetos de esta clase:
Si tiene una cadena json que necesita analizar en la clase Persona, hágalo así:
fuente
Las respuestas de Olivers son muy claras, pero si está buscando una solución en angular js, he escrito un buen módulo llamado Angular-jsClass que facilita esta tarea, tener objetos definidos en notación literal siempre es malo cuando apunta a un gran proyecto pero diciendo que los desarrolladores enfrentan un problema que exactamente BMiner dijo, cómo serializar un json para prototipos o objetos de notación de constructor
https://github.com/imalhasaranga/Angular-JSClass
fuente