Je sais comment analyser une chaîne JSON et la transformer en objet JavaScript. Vous pouvez utiliser JSON.parse()
dans les navigateurs modernes (et IE9 +).
C'est génial, mais comment puis-je prendre cet objet JavaScript et le transformer en un objet JavaScript particulier (c'est-à-dire avec un certain prototype)?
Par exemple, supposons que vous ayez:
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
Encore une fois, je ne me demande pas comment convertir une chaîne JSON en un objet JavaScript générique. Je veux savoir comment convertir une chaîne JSON en un objet "Foo". Autrement dit, mon objet devrait maintenant avoir une fonction «test» et les propriétés «a» et «b».
MISE À JOUR Après avoir fait quelques recherches, j'ai pensé à ceci ...
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);
Ça marchera?
MISE À JOUR Mai 2017 : La façon «moderne» de faire cela est via Object.assign
, mais cette fonction n'est pas disponible dans IE 11 ou les navigateurs Android plus anciens.
Réponses:
Les réponses actuelles contiennent beaucoup de code roulé à la main ou de bibliothèque. Ce n'est pas nécessaire.
Utilisez
JSON.parse('{"a":1}')
pour créer un objet simple.Utilisez l'une des fonctions standardisées pour définir le prototype:
Object.assign(new Foo, { a: 1 })
Object.setPrototypeOf({ a: 1 }, Foo.prototype)
la source
Object.setPrototypeOf(...)
. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…setPrototypeOf
être des descripteurs de propriété.Voir un exemple ci-dessous (cet exemple utilise l'objet JSON natif). Mes modifications sont commentées en MAJUSCULES:
la source
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];}}
. Cela suppose que vous vous attendez à ce que le serveur remplisse toutes les propriétés, l'OMI devrait également lancer si obj.hasOwnProperty () échoue ...Voulez-vous ajouter une fonctionnalité de sérialisation / désérialisation JSON, n'est-ce pas? Ensuite, regardez ceci:
Vous voulez réaliser ceci:
toJson () est une méthode normale.
fromJson () est une méthode statique.
Implémentation :
Utilisation :
Remarque: Si vous voulez , vous pouvez modifier les définitions de propriétés comme
this.title
,this.author
, etc parvar title
,var author
, etc. et les ajouter getters à accomplir la définition UML.la source
toJson()
méthode - qu'elle ait des propriétés individuelles codées en dur ou qu'elle utilise un pour chacune - devra ajouter des codes d'échappement de barre oblique inverse pour certains caractères qui pourraient être dans chaque propriété de chaîne. (Un titre de livre peut avoir des guillemets, par exemple.)JSON.stringify()
plutôt que d'écrire à JSon () moi-même. Plus besoin de réinventer la roue maintenant que tous les navigateurs modernes la prennent en charge.serializable = ['title', 'author', ...]
.JSON.stringify(serializable.reduce((obj, prop) => {...obj, [prop]: this[prop]}, {}))
Un article de blog que j'ai trouvé utile: Comprendre les prototypes JavaScript
Vous pouvez jouer avec la propriété __proto__ de l'objet.
Cela permet à fooJSON d'hériter du prototype Foo.
Je ne pense pas que cela fonctionne dans IE, cependant ... du moins d'après ce que j'ai lu.
la source
__proto__
est obsolète depuis longtemps . De plus, pour des raisons de performances, il n'est pas recommandé de modifier la propriété interne [[Prototype]] d'un objet déjà créé (par paramétrage__proto__
ou par tout autre moyen).[[prototype]]
et cela ne semble pas pertinent dans Chrome. Dans Firefox, appeler new est plus lent que d'utiliser prototype, et Object.create est le plus rapide. Je suppose que le problème avec FF est que le premier test est plus lent que le dernier, l'ordre d'exécution compte. Dans Chrome, tout fonctionne à peu près à la même vitesse. Je veux dire l'accès à la propriété et la nvocation de méthodes. La créatine est plus rapide avec le nouveau, mais ce n'est pas si important. voir: jsperf.com/prototype-change-test-8874874/1 et: jsperf.com/prototype-changed-method-callObject.setPrototypeOf(fooJSON, Foo.prototype)
au lieu de réglerfooJSON.__proto__
... non?Est-ce que je manque quelque chose dans la question ou pourquoi personne n'a mentionné le
reviver
paramètre deJSON.parse
depuis 2011?Voici un code simpliste pour une solution qui fonctionne: https://jsfiddle.net/Ldr2utrr/
PS: Votre question prête à confusion: >> C'est génial, mais comment puis-je prendre cet objet JavaScript et le transformer en un objet JavaScript particulier (c'est-à-dire avec un certain prototype)? contredit le titre, où vous posez des questions sur l'analyse JSON, mais le paragraphe cité pose des questions sur le remplacement du prototype d'objet d'exécution JS.
la source
Une autre approche pourrait être utilisée
Object.create
. Comme premier argument, vous passez le prototype, et pour le second vous passez une carte des noms de propriétés aux descripteurs:la source
J'aime ajouter un argument facultatif au constructeur et appeler
Object.assign(this, obj)
, puis gérer toutes les propriétés qui sont des objets ou des tableaux d'objets eux-mêmes:la source
Par souci d'exhaustivité, voici un simple one-liner avec lequel j'ai fini (je n'avais pas besoin de vérifier les propriétés non Foo):
la source
J'ai créé un package appelé json-dry . Il prend en charge les références (circulaires) ainsi que les instances de classe.
Vous devez définir 2 nouvelles méthodes dans votre classe (
toDry
sur le prototype et enunDry
tant que méthode statique), enregistrer la classe (Dry.registerClass
), et c'est parti.la source
Bien que ce ne soit pas techniquement ce que vous voulez, si vous connaissez à l'avance le type d'objet que vous voulez gérer, vous pouvez utiliser les méthodes call / apply du prototype de votre objet connu.
tu peux changer ça
pour ça
la source
J'ai combiné les solutions que j'ai pu trouver et les ai compilées en une solution générique qui peut analyser automatiquement un objet personnalisé et tous ses champs de manière récursive afin que vous puissiez utiliser des méthodes de prototype après la désérialisation.
Une hypothèse est que vous avez défini un champ spécial qui indique son type dans chaque objet auquel vous souhaitez appliquer son type automatiquement (
this.__type
dans l'exemple).usage:
Fonction d'affectation de type (elle fonctionne de manière récursive pour attribuer des types à tous les objets imbriqués; elle itère également dans les tableaux pour trouver les objets appropriés):
la source
La réponse actuellement acceptée ne fonctionnait pas pour moi. Vous devez utiliser Object.assign () correctement:
Vous créez normalement des objets de cette classe:
Si vous avez une chaîne json que vous devez analyser dans la classe Person, procédez comme suit:
la source
Les réponses d'Olivers sont très claires, mais si vous cherchez une solution en angular js, j'ai écrit un joli module appelé Angular-jsClass qui fait cette facilité, avoir des objets définis en notation litarale est toujours mauvais lorsque vous visez un gros projet mais en disant que les développeurs sont confrontés à un problème, exactement ce que dit BMiner, comment sérialiser un json en objets de notation prototype ou constructeur
https://github.com/imalhasaranga/Angular-JSClass
la source