javascript - mostrar - json.parse array
Parse JSON String en un prototipo de objeto particular en JavaScript (12)
¿Desea agregar la funcionalidad de serialización / deserialización de JSON, ¿verdad? Entonces mira esto:
Quieres lograr esto:
toJson () es un método normal.
fromJson () es un método estático.
Implementación :
var Book = function (title, author, isbn, price, stock){
this.title = title;
this.author = author;
this.isbn = isbn;
this.price = price;
this.stock = stock;
this.toJson = function (){
return ("{" +
"/"title/":/"" + this.title + "/"," +
"/"author/":/"" + this.author + "/"," +
"/"isbn/":/"" + this.isbn + "/"," +
"/"price/":" + this.price + "," +
"/"stock/":" + this.stock +
"}");
};
};
Book.fromJson = function (json){
var obj = JSON.parse (json);
return new Book (obj.title, obj.author, obj.isbn, obj.price, obj.stock);
};
Uso :
var book = new Book ("t", "a", "i", 10, 10);
var json = book.toJson ();
alert (json); //prints: {"title":"t","author":"a","isbn":"i","price":10,"stock":10}
var book = Book.fromJson (json);
alert (book.title); //prints: t
Nota: Si lo desea, puede cambiar todas las definiciones de propiedades como this.title
, this.author
, etc. por var title
, var author
, etc. y agregar getters a ellas para lograr la definición de UML.
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 de JavaScript y convertirlo en un Objeto de JavaScript particular (es decir, con un cierto prototipo)?
Por ejemplo, supongamos que tienes:
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
De nuevo, 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 de mayo de 2017 : la forma "moderna" de hacerlo es a través de Object.assign
, pero esta función no está disponible en los navegadores de IE 11 o anteriores de Android.
¿Me estoy perdiendo algo en la pregunta o por qué nadie mencionó el parámetro reviver de reviver desde 2011?
Aquí hay un código simplista para la solución que funciona: https://jsfiddle.net/Ldr2utrr/
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}`, function(key,value){
if(key!=="") return value; //logic of course should be more complex for handling nested objects etc.
let res = new Foo();
res.a = value.a;
res.b = value.b;
return res;
});
// Here you already get Foo object back
alert(fooJSON.test() ); //Prints 12
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 al título, donde se pregunta por el análisis JSON, pero el párrafo citado pregunta sobre el reemplazo del prototipo de objeto de tiempo de ejecución de JS.
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 recursivamente para que pueda usar métodos prototipo después de la deserialización.
Una suposición es que usted definió un archivo especial que indica su tipo en cada objeto que desea aplicar, es de tipo automático ( this.__type
en el ejemplo).
function Msg(data) {
//... your init code
this.data = data //can be another object or an array of objects of custom types.
//If those objects defines `this.__type'', their types will be assigned automatically as well
this.__type = "Msg"; // <- store the object''s type to assign it automatically
}
Msg.prototype = {
createErrorMsg: function(errorMsg){
return new Msg(0, null, errorMsg)
},
isSuccess: function(){
return this.errorMsg == null;
}
}
uso:
var responseMsg = //json string of Msg object received;
responseMsg = assignType(responseMsg);
if(responseMsg.isSuccess()){ // isSuccess() is now available
//furhter logic
//...
}
Escriba la función de asignación (funciona recursivamente para asignar tipos a cualquier objeto anidado, sino que también itera a través de matrices para encontrar los objetos adecuados):
function assignType(object){
if(object && typeof(object) === ''object'' && window[object.__type]) {
object = assignTypeRecursion(object.__type, object);
}
return object;
}
function assignTypeRecursion(type, object){
for (var key in object) {
if (object.hasOwnProperty(key)) {
var obj = object[key];
if(Array.isArray(obj)){
for(var i = 0; i < obj.length; ++i){
var arrItem = obj[i];
if(arrItem && typeof(arrItem) === ''object'' && window[arrItem.__type]) {
obj[i] = assignTypeRecursion(arrItem.__type, arrItem);
}
}
} else if(obj && typeof(obj) === ''object'' && window[obj.__type]) {
object[key] = assignTypeRecursion(obj.__type, obj);
}
}
}
return Object.assign(new window[type](), object);
}
En aras de la exhaustividad, aquí hay un sencillo delineador con el que terminé (no tuve necesidad de buscar propiedades que no pertenezcan a Foo):
var Foo = function(){ this.bar = 1; };
// angular version
var foo = angular.extend(new Foo(), angular.fromJson(''{ "bar" : 2 }''));
// jquery version
var foo = jQuery.extend(new Foo(), jQuery.parseJSON(''{ "bar" : 3 }''));
La respuesta de Olivers es muy clara, pero si estás buscando una solución en js angulares, he escrito un bonito módulo llamado Angular-jsClass que lo hace fácil, tener objetos definidos en notación litaral siempre es malo cuando estás apuntando a un gran proyecto pero diciendo que los desarrolladores se enfrentan a un problema que exactamente dice BMiner, cómo serializar un objeto json para prototipos o objetos de notación de constructores
var jone = new Student();
jone.populate(jsonString); // populate Student class with Json string
console.log(jone.getName()); // Student Object is ready to use
Las respuestas actuales contienen una gran cantidad de código enrollado a mano o de la biblioteca. Esto no es necesario.
Use
JSON.parse(''{"a":1}'')
para crear un objeto simple.Use una de las funciones estandarizadas para establecer el prototipo:
-
Object.assign(new Foo, { a: 1 })
-
Object.setPrototypeOf({ a: 1 }, Foo.prototype)
-
Me gusta agregar un argumento opcional al constructor y llamar a Object.assign(this, obj)
, y luego manejar cualquier propiedad que sea un objeto o una matriz de objetos:
constructor(obj) {
if (obj != null) {
Object.assign(this, obj);
if (this.ingredients != null) {
this.ingredients = this.ingredients.map(x => new Ingredient(x));
}
}
}
Si bien, técnicamente esto no es lo que quieres, si conoces de antemano el tipo de objeto que deseas manejar, puedes usar los métodos de llamada / aplicación del prototipo de tu objeto conocido.
puedes cambiar esto
alert(fooJSON.test() ); //Prints 12
a esto
alert(Foo.prototype.test.call(fooJSON); //Prints 12
Un enfoque alternativo podría ser el uso de Object.create
. Como primer argumento, pasas el prototipo, y para el segundo pasas un mapa de nombres de propiedad a las descripciones:
function SomeConstructor() {
};
SomeConstructor.prototype = {
doStuff: function() {
console.log("Some stuff");
}
};
var jsonText = ''{ "text": "hello wrold" }'';
var deserialized = JSON.parse(jsonText);
// This will build a property to descriptor map
// required for #2 argument of Object.create
var descriptors = Object.keys(deserialized)
.reduce(function(result, property) {
result[property] = Object.getOwnPropertyDescriptor(deserialized, property);
}, {});
var obj = Object.create(SomeConstructor.prototype, descriptors);
Una publicación de blog que encontré útil: comprensión de los prototipos de JavaScript
Puedes jugar con la propiedad __proto__ del Objeto.
var fooJSON = jQuery.parseJSON({"a":4, "b": 3});
fooJSON.__proto__ = Foo.prototype;
Esto permite a fooJSON heredar el prototipo de Foo.
No creo que esto funcione en IE, aunque ... al menos por lo que he leído.
Vea un ejemplo a continuación (este ejemplo usa el objeto JSON nativo). Mis cambios se comentan en CAPITALES:
function Foo(obj) // CONSTRUCTOR CAN BE OVERLOADED WITH AN OBJECT
{
this.a = 3;
this.b = 2;
this.test = function() {return this.a*this.b;};
// IF AN OBJECT WAS PASSED THEN INITIALISE PROPERTIES FROM THAT OBJECT
for (var prop in obj) this[prop] = obj[prop];
}
var fooObj = new Foo();
alert(fooObj.test() ); //Prints 6
// INITIALISE A NEW FOO AND PASS THE PARSED JSON OBJECT TO IT
var fooJSON = new Foo(JSON.parse(''{"a":4,"b":3}''));
alert(fooJSON.test() ); //Prints 12