J'ai une définition d'objet JavaScript qui contient une référence circulaire: elle a une propriété qui référence l'objet parent.
Il comporte également des fonctions que je ne souhaite pas transmettre au serveur. Comment pourrais-je sérialiser et désérialiser ces objets?
J'ai lu que la meilleure méthode consiste à utiliser le stringify de Douglas Crockford. Toutefois, l'erreur suivante s'affiche dans Chrome:
TypeError: Conversion de structure circulaire en JSON
Le code:
function finger(xid, xparent){
this.id = xid;
this.xparent;
//other attributes
}
function arm(xid, xparent){
this.id = xid;
this.parent = xparent;
this.fingers = [];
//other attributes
this.moveArm = function() {
//moveArm function details - not included in this testcase
alert("moveArm Executed");
}
}
function person(xid, xparent, xname){
this.id = xid;
this.parent = xparent;
this.name = xname
this.arms = []
this.createArms = function () {
this.arms[this.arms.length] = new arm(this.id, this);
}
}
function group(xid, xparent){
this.id = xid;
this.parent = xparent;
this.people = [];
that = this;
this.createPerson = function () {
this.people[this.people.length] = new person(this.people.length, this, "someName");
//other commands
}
this.saveGroup = function () {
alert(JSON.stringify(that.people));
}
}
Ceci est un test que j'ai créé pour cette question. Il y a des erreurs dans ce code, mais j'ai essentiellement des objets dans les objets et une référence transmise à chaque objet pour montrer ce qu'est l'objet parent lors de la création de l'objet. Chaque objet contient également des fonctions que je ne veux pas hiérarchiser. Je veux juste les propriétés telles que le Person.Name
.
Comment puis-je sérialiser avant d'envoyer au serveur et le désérialiser en supposant que le même JSON est renvoyé?
Structure circulaire Une erreur survient lorsque vous avez une propriété de l'objet qui est directement l'objet lui-même (a -> a
) ou indirectement (a -> b -> a
).
Pour éviter le message d'erreur, indiquez à JSON.stringify ce qu'il faut faire lorsqu'il rencontre une référence circulaire. Par exemple, si vous avez une personne qui pointe vers une autre personne ("parent"), qui peut (ou non) pointer vers la personne d'origine, procédez comme suit:
JSON.stringify( that.person, function( key, value) {
if( key == 'parent') { return value.id;}
else {return value;}
})
Le deuxième paramètre de stringify
est une fonction de filtre . Ici, il convertit simplement l'objet référencé en son ID, mais vous êtes libre de faire ce que vous voulez pour casser la référence circulaire.
Vous pouvez tester le code ci-dessus avec les éléments suivants:
function Person( params) {
this.id = params['id'];
this.name = params['name'];
this.father = null;
this.fingers = [];
// etc.
}
var me = new Person({ id: 1, name: 'Luke'});
var him = new Person( { id:2, name: 'Darth Vader'});
me.father = him;
JSON.stringify(me); // so far so good
him.father = me; // time travel assumed :-)
JSON.stringify(me); // "TypeError: Converting circular structure to JSON"
// But this should do the job:
JSON.stringify(me, function( key, value) {
if(key == 'father') {
return value.id;
} else {
return value;
};
});
En passant, je choisirais un nom d'attribut différent de "parent
" puisqu'il s'agit d'un mot réservé dans plusieurs langues (et dans le DOM). Cela tend à semer la confusion sur la route ...
Il semble que dojo puisse représenter des références circulaires en JSON sous la forme: {"id":"1","me":{"$ref":"1"}}
Voici un exemple:
require(["dojox/json/ref"], function(){
var me = {
name:"Kris",
father:{name:"Bill"},
mother:{name:"Karen"}
};
me.father.wife = me.mother;
var jsonMe = dojox.json.ref.toJson(me); // serialize me
alert(jsonMe);
});
Produit:
{
"name":"Kris",
"father":{
"name":"Bill",
"wife":{
"name":"Karen"
}
},
"mother":{
"$ref":"#father.wife"
}
}
Remarque: Vous pouvez également désérialiser ces objets circulaires référencés à l'aide de la commande dojox.json.ref.fromJson
méthode.
Autres ressources:
Comment sérialiser un noeud DOM en JSON même s’il existe des références circulaires?
JSON.stringify ne peut pas représenter des références circulaires
J'ai trouvé deux modules appropriés pour gérer les références circulaires en JSON.
L'un ou l'autre devrait répondre à vos besoins.
Cela s'est produit sur ce fil parce que je devais enregistrer des objets complexes sur une page, car le débogage à distance n'était pas possible dans ma situation particulière. Trouvé le propre cycle.js de Douglas Crockford (l'incepteur de JSON), qui annote les références circulaires sous forme de chaînes de sorte qu'elles puissent être reconnectées après l'analyse. La copie profonde décyclée est sécurisée pour passer par JSON.stringify. Prendre plaisir!
https://github.com/douglascrockford/JSON-js
cycle.js: Ce fichier contient deux fonctions, JSON.decycle et JSON.retrocycle, qui permettent d’encoder des structures cycliques et des dags en JSON, puis de les récupérer. Cette fonctionnalité n’est pas fournie par ES5. JSONPath est utilisé pour représenter les liens.