J'ai un gros objet que je veux convertir en JSON et envoyer. Cependant, il a une structure circulaire. Je veux lancer toutes les références circulaires existantes et envoyer tout ce qui peut être stratifié. Comment je fais ça?
Merci.
var obj = {
a: "foo",
b: obj
}
Je veux stringifier obj en:
{"a":"foo"}
javascript
json
node.js
Harry
la source
la source
Réponses:
À utiliser
JSON.stringify
avec un remplaçant personnalisé. Par exemple:Le remplaçant dans cet exemple n'est pas correct à 100% (selon votre définition de "doublon"). Dans le cas suivant, une valeur est ignorée:
Mais le concept est le suivant: utilisez un remplaçant personnalisé et gardez une trace des valeurs des objets analysés.
En tant que fonction utilitaire écrite en es6:
la source
Node.prototype.toJSON = function() { return 'whatever you think that is right'; };
(si vous voulez quelque chose de plus générique / spécifique, essayez simplement n'importe quoi dans l'arborescence du prototype: HTMLDivElement implémente HTMLElement implémente Element implémente Node implémente EventTarget; remarque: cela peut dépendre du navigateur, l'arborescence précédente est vraie pour Chrome)var a={id:1}; JSON.stringify([a,a]);
cache
il sera inaccessible developer.mozilla.org/en-US/docs/Web/JavaScript/…Dans Node.js, vous pouvez utiliser util.inspect (object) . Il remplace automatiquement les liens circulaires par "[Circulaire]".
Bien qu'il soit intégré (aucune installation n'est requise) , vous devez l'importer
Pour l'utiliser, appelez simplementSachez également que vous pouvez passer un objet d'options à inspecter (voir le lien ci-dessus)
S'il vous plaît, lisez et félicitez les commentateurs ci-dessous ...
la source
var util = require('util');
obj_str = util.inspect(thing)
, PAS <s>garbage_str = JSON.stringify(util.inspect(thing))
</s>Je me demande pourquoi personne n'a encore posté la bonne solution à partir de la page MDN ...
Les valeurs vues doivent être stockées dans un ensemble , pas dans un tableau (le remplaçant est appelé sur chaque élément ) et il n'est pas nécessaire d'essayer
JSON.stringify
chaque élément de la chaîne menant à une référence circulaire.Comme dans la réponse acceptée, cette solution supprime toutes les valeurs répétitives , pas seulement les valeurs circulaires. Mais au moins, il n'a pas de complexité exponentielle.
la source
replacer = () => { const seen = new WeakSet(); return (key, value) => { if (typeof value === "object" && value !== null) { if (seen.has(value)) { return; } seen.add(value); } return value; }; } () => { const seen = new WeakSet(); return (key, value) => { if (typeof value === "object" && value !== null) { if (seen.has(value)) { return; } seen.add(value); … JSON.stringify({a:1, b: '2'}, replacer)
revientundefined
en chromefais juste
puis dans votre fichier js
https://github.com/WebReflection/circular-json
REMARQUE: je n'ai rien à voir avec ce package. Mais je l'utilise pour cela.
Mise à jour 2020
Veuillez noter que CircularJSON est en maintenance uniquement et aplati est son successeur.
la source
JSON
par principe.Flatted.stringify({blah: 1})
résultats en[{"blah":1}]
) Je vois que quelqu'un a essayé de soulever un problème à ce sujet, et l'auteur les a réprimandés et a verrouillé le problème aux commentaires.J'ai vraiment aimé la solution de Trindaz - plus verbeuse, mais elle avait quelques bugs. Je les ai réparés pour ceux qui aiment ça aussi.
De plus, j'ai ajouté une limite de longueur à mes objets de cache.
Si l'objet que j'imprime est vraiment grand - je veux dire infiniment grand - je veux limiter mon algorithme.
la source
@ La réponse de RobW est correcte, mais c'est plus performant! Parce qu'il utilise un hashmap / set:
la source
{"a":{"b":{"a":"d"}}}
et même la suppression des nœuds ayant un objet vide {}Notez qu'il existe également une
JSON.decycle
méthode implémentée par Douglas Crockford. Voir son cycle.js . Cela vous permet de stringifier presque n'importe quelle structure standard:Vous pouvez également recréer un objet d'origine avec la
retrocycle
méthode. Vous n'avez donc pas à supprimer les cycles des objets pour les stringifier.Cependant, cela ne fonctionnera pas pour les nœuds DOM (qui sont la cause typique des cycles dans des cas d'utilisation réels). Par exemple, cela lancera:
J'ai fait une fourchette pour résoudre ce problème (voir ma fourche cycle.js ). Cela devrait fonctionner correctement:
Notez que dans ma fourchette
JSON.decycle(variable)
fonctionne comme dans l'original et lèvera une exception lorsque lesvariable
nœuds / éléments DOM contiennent.Lorsque vous utilisez,
JSON.decycle(variable, true)
vous acceptez le fait que le résultat ne sera pas réversible (le rétrocycle ne recréera pas les nœuds DOM). Les éléments DOM doivent cependant être identifiables dans une certaine mesure. Par exemple, si undiv
élément a un identifiant, il sera remplacé par une chaîne"div#id-of-the-element"
.la source
JSON.decycle(a, true)
ce qui se passe lorsque vous passez true comme paramètre à la fonction de recyclage.stringifyNodes
option vraie dans le fork. Cela videra par exemplediv
avec id = « some-id » à la chaîne:div#some-id
. Vous éviterez certains problèmes, mais vous ne pourrez pas effectuer de rétro-cycle complet.Je recommanderais de vérifier json-stringify-safe de @ isaacs - il est utilisé dans NPM.
À installer:
Utiliser:
Cela donne:
la source
Pour les futurs googleurs à la recherche d'une solution à ce problème lorsque vous ne connaissez pas les clés de toutes les références circulaires, vous pouvez utiliser un wrapper autour de la fonction JSON.stringify pour exclure les références circulaires. Voir un exemple de script sur https://gist.github.com/4653128 .
La solution se résume essentiellement à conserver une référence aux objets précédemment imprimés dans un tableau et à vérifier cela dans une fonction de remplacement avant de renvoyer une valeur. Il est plus contraignant que d'exclure uniquement les références circulaires, car il exclut également d'imprimer un objet deux fois, l'un des effets secondaires étant d'éviter les références circulaires.
Exemple de wrapper:
la source
if(printedObjIndex)
pendant que vous devez écrire,if(printedObjIndex==false)
carindex
peut également être0
traduit en,false
sauf indication contraire explicite.===
?0 == false
esttrue
,0 === false
estfalse
. ; ^) Mais je préfère ne pas initialiserprintedObjIndex
à false, car alors vous pouvez vérifierundefined
si vous (enfin, Trindaz) ne mélange pas les métaphores aussi étrangement.Utilisez la méthode JSON.stringify avec un remplaçant. Lisez cette documentation pour plus d'informations. http://msdn.microsoft.com/en-us/library/cc836459%28v=vs.94%29.aspx
Trouvez un moyen de remplir le tableau de remplacement avec des références cycliques. Vous pouvez utiliser la méthode typeof pour rechercher si une propriété est de type 'objet' (référence) et une vérification d'égalité exacte (===) pour vérifier la référence circulaire.
la source
var obj = {foo:obj}
ne crée pas de référence circulaire. Au lieu de cela, il crée un objet dont l'foo
attribut fait référence à la valeur précédente deobj
(undefined
s'il n'est pas précédemment défini, déclaré à cause devar obj
).Si
résulte en un
Ensuite, vous voudrez peut-être imprimer comme ceci:
la source
évalue à:
avec la fonction:
la source
Je sais que c'est une vieille question, mais je voudrais suggérer un package NPM que j'ai créé appelé smart-circulaire , qui fonctionne différemment des autres méthodes proposées. C'est particulièrement utile si vous utilisez des objets gros et profonds .
Certaines fonctionnalités sont:
Remplacement des références circulaires ou des structures simplement répétées à l'intérieur de l'objet par le chemin menant à sa première occurrence (pas seulement la chaîne [circulaire] );
En recherchant des circularités dans une recherche en largeur, le package garantit que ce chemin est aussi petit que possible, ce qui est important lorsqu'il s'agit d'objets très gros et profonds, où les chemins peuvent devenir ennuyeusement longs et difficiles à suivre (le remplacement personnalisé dans JSON.stringify fait un DFS);
Permet des remplacements personnalisés, pratiques pour simplifier ou ignorer les parties moins importantes de l'objet;
Enfin, les chemins sont écrits exactement de la manière nécessaire pour accéder au champ référencé, ce qui peut vous aider à déboguer.
la source
Le deuxième argument de JSON.stringify () vous permet également de spécifier un tableau de noms de clés qui doivent être préservés de chaque objet qu'il rencontre dans vos données. Cela peut ne pas fonctionner pour tous les cas d'utilisation, mais c'est une solution beaucoup plus simple.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
Remarque: Étrangement, la définition d'objet d'OP ne génère pas d'erreur de référence circulaire dans le dernier Chrome ou Firefox. La définition de cette réponse a été modifiée de sorte qu'il a fait une erreur.
la source
Pour mettre à jour la réponse de surcharger le fonctionnement de JSON (probablement non recommandé, mais super simple), n'utilisez pas
circular-json
(c'est obsolète). Utilisez plutôt le successeur, aplati:https://www.npmjs.com/package/flatted
Emprunté de l'ancienne réponse ci-dessus de @ user1541685, mais remplacé par la nouvelle:
npm i --save flatted
puis dans votre fichier js
la source
J'ai trouvé la bibliothèque circular-json sur github et cela a bien fonctionné pour mon problème.
Quelques bonnes fonctionnalités que j'ai trouvées utiles:
la source
Je résous ce problème comme ceci:
la source
_class: ClassName { data: "here" }
, j'ai donc ajouté la règle suivante.replace(/(\w+) {/g, '{ __ClassName__: "$1", ')
. Dans mon cas, j'essayais de voir à quoi ressemblait un objet de requête http.Je sais que cette question est ancienne et a beaucoup de bonnes réponses, mais je poste cette réponse en raison de sa nouvelle saveur (es5 +)
Afficher l'extrait de code
la source
Bien que cela ait été répondu suffisamment, vous pouvez également supprimer explicitement la propriété en question avant la stringification en utilisant l'
delete
opérateur.supprimer l'opérateur
cela supprimera la nécessité de créer ou de maintenir une logique complexe pour supprimer les références circulaires.
la source
la source
une autre solution pour résoudre ce problème avec ce type d'objets est que l'utilisation de cette bibliothèque
https://github.com/ericmuyser/stringy
c'est simple et vous pouvez en quelques étapes simples résoudre ce problème.
la source
Sur la base des autres réponses, je me retrouve avec le code suivant. Cela fonctionne assez bien avec des références circulaires, des objets avec des constructeurs personnalisés.
De l'objet donné à sérialiser,
Lien Github - DecycledJSON
Exemple d'utilisation 1:
Exemple d'utilisation 2:
la source
Essaye ça:
la source
seen.push(value)
= -D? Commefor (var key in value) {value[key] = circular_replacer(value[key]);}
Dans ma solution, si vous rencontrez un cycle, il ne dit pas seulement "cycle" (ou rien), il dit quelque chose comme foo: voir l'objet n ° 42 ci-dessus, et pour voir où foo pointe vers vous, faites défiler vers le haut et recherchez pour l'objet # 42 (chaque objet, quand il démarre, dit l'objet # xxx avec un entier xxx)
Fragment:
la source