web-dev-qa-db-fra.com

JSON.stringify, évitez TypeError: conversion de structure circulaire en JSON

J'ai un gros objet que je veux convertir en JSON et envoyer. Cependant, il a une structure circulaire. Je veux jeter 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 structurer obj en:

{"a":"foo"}
464
Harry

Utilisez JSON.stringify avec un remplaçant personnalisé. Par exemple:

// Demo: Circular reference
var o = {};
o.o = o;

// Note: cache should not be re-used by repeated calls to JSON.stringify.
var cache = [];
JSON.stringify(o, function(key, value) {
    if (typeof value === 'object' && value !== null) {
        if (cache.indexOf(value) !== -1) {
            // Duplicate reference found
            try {
                // If this value does not reference a parent it can be deduped
                return JSON.parse(JSON.stringify(value));
            } catch (error) {
                // discard key if value cannot be deduped
                return;
            }
        }
        // Store value in our collection
        cache.Push(value);
    }
    return value;
});
cache = null; // Enable garbage collection

Le remplacement dans cet exemple n'est pas correct à 100% (selon votre définition de "dupliquer"). Dans le cas suivant, une valeur est ignorée:

var a = {b:1}
var o = {};
o.one = a;
o.two = a;
// one and two point to the same object, but two is discarded:
JSON.stringify(o, ...);

Mais le concept est valable: utilisez un remplaçant personnalisé et suivez les valeurs des objets analysés.

456
Rob W

Dans Node.js, vous pouvez utiliser util.inspect (object) . Il remplace automatiquement les liens circulaires par "[Circulaire]".


Bien que intégré (aucune installation n'est requise), vous devez l'importer

import * as util from 'util' // has no default export
import { inspect } from 'util' // or directly
// or 
var util = require('util')
console.log(util.inspect(myObject))

Sachez également que vous pouvez passer l'objet options à inspecter (voir le lien ci-dessus)

inspect(myObject[, options: {showHidden, depth, colors, showProxy, ...moreOptions}])



S'il vous plaît, lisez et félicitez les commentateurs ci-dessous ...

486
Erel Segal-Halevi

fais juste 

npm i --save circular-json

puis dans votre fichier js

const JSON = require('circular-json');
...
const json = JSON.stringify(obj);

Tu pourrais aussi faire 

const CircularJSON = require('circular-json');

https://github.com/WebReflection/circular-json

NOTE: je n’ai rien à voir avec ce paquet. Mais je l'utilise pour cela.

55
user1541685

J'ai vraiment aimé la solution de Trindaz - plus verbeuse, mais il y avait quelques bugs. Je les ai corrigés pour ceux qui aiment aussi.

De plus, j'ai ajouté une limite de longueur à mes objets en cache. 

Si l'objet que j'imprime est vraiment gros - je veux dire infiniment grand - je veux limiter mon algorithme. 

JSON.stringifyOnce = function(obj, replacer, indent){
    var printedObjects = [];
    var printedObjectKeys = [];

    function printOnceReplacer(key, value){
        if ( printedObjects.length > 2000){ // browsers will not print more than 20K, I don't see the point to allow 2K.. algorithm will not be fast anyway if we have too many objects
        return 'object too long';
        }
        var printedObjIndex = false;
        printedObjects.forEach(function(obj, index){
            if(obj===value){
                printedObjIndex = index;
            }
        });

        if ( key == ''){ //root element
             printedObjects.Push(obj);
            printedObjectKeys.Push("root");
             return value;
        }

        else if(printedObjIndex+"" != "false" && typeof(value)=="object"){
            if ( printedObjectKeys[printedObjIndex] == "root"){
                return "(pointer to root)";
            }else{
                return "(see " + ((!!value && !!value.constructor) ? value.constructor.name.toLowerCase()  : typeof(value)) + " with key " + printedObjectKeys[printedObjIndex] + ")";
            }
        }else{

            var qualifiedKey = key || "(empty key)";
            printedObjects.Push(value);
            printedObjectKeys.Push(qualifiedKey);
            if(replacer){
                return replacer(key, value);
            }else{
                return value;
            }
        }
    }
    return JSON.stringify(obj, printOnceReplacer, indent);
};
46
guy mograbi

Notez qu'il existe également une méthode JSON.decycle implémentée par Douglas Crockford. Voir son cycle.js . Cela vous permet de structurer presque toutes les structures standard:

var a = [];
a[0] = a;
a[1] = 123;
console.log(JSON.stringify(JSON.decycle(a)));
// result: '[{"$ref":"$"},123]'.

Vous pouvez également recréer l'objet d'origine avec la méthode retrocycle. Il n'est donc pas nécessaire de supprimer les cycles des objets pour les renforcer.

Cependant, cela pas fonctionnera pour les nœuds DOM (qui sont la cause typique des cycles dans les cas d'utilisation réels). Par exemple, cela jettera:

var a = [document.body];
console.log(JSON.stringify(JSON.decycle(a)));

J'ai créé un fork pour résoudre ce problème (voir mon fork cycle.js ) Cela devrait bien fonctionner:

var a = [document.body];
console.log(JSON.stringify(JSON.decycle(a, true)));

Notez que dans ma fourche, JSON.decycle(variable) fonctionne comme dans l'original et lève une exception lorsque la variable variable contient des nœuds/éléments DOM.

Lorsque vous utilisez JSON.decycle(variable, true), vous acceptez le fait que le résultat ne sera pas réversible (retrocycle ne recrée pas de nœuds DOM). Les éléments DOM doivent toutefois être identifiables dans une certaine mesure. Par exemple, si un élément div a un identifiant, il sera remplacé par une chaîne "div#id-of-the-element".

35
Nux

La réponse de @ RobW est correcte, mais elle est plus performante! Parce qu'il utilise un hashmap/set:

const customStringify = function (v) {
  const cache = new Set();
  return JSON.stringify(v, function (key, value) {
    if (typeof value === 'object' && value !== null) {
      if (cache.has(value)) {
        // Circular reference found
        try {
          // If this value does not reference a parent it can be deduped
         return JSON.parse(JSON.stringify(value));
        }
        catch (err) {
          // discard key if value cannot be deduped
         return;
        }
      }
      // Store value in our set
      cache.add(value);
    }
    return value;
  });
};
30
Alexander Mills

Je me demande pourquoi personne n'a posté la solution appropriée de la page MDN pour l'instant ...

const getCircularReplacer = () => {
  const seen = new WeakSet();
  return (key, value) => {
    if (typeof value === "object" && value !== null) {
      if (seen.has(value)) {
        return;
      }
      seen.add(value);
    }
    return value;
  };
};

JSON.stringify(circularReference, getCircularReplacer());

Les valeurs vues doivent être stockées dans un ensemble, pas dans un tableau (le replaceur est appelé sur chaque élément) et il n'est pas nécessaire d'essayer JSON.stringifychaque élément dans la chaîne menant à une référence circulaire .

Comme dans la réponse acceptée, cette solution supprime toutes les valeurs répétées, pas uniquement les valeurs circulaires. Mais au moins, il n’a pas de complexité exponentielle.

26
Artur Klesun

Je vous recommande de vérifier json-stringify-safe de @ isaacs--, utilisé dans NPM.

BTW- si vous n'utilisez pas Node.js, vous pouvez simplement copier et coller les lignes 4 à 27 de la partie pertinente du code source .

À installer:

$ npm install json-stringify-safe --save

Utiliser:

// Require the thing
var stringify = require('json-stringify-safe');

// Take some nasty circular object
var theBigNasty = {
  a: "foo",
  b: theBigNasty
};

// Then clean it up a little bit
var sanitized = JSON.parse(stringify(theBigNasty));

Cela donne:

{
  a: 'foo',
  b: '[Circular]'
}

Notez que, comme avec la fonction Vanilla JSON.stringify mentionnée par @Rob W, vous pouvez également personnaliser le comportement de désinfection en transmettant une fonction "replacer" en tant que second argument à stringify(). Si vous avez besoin d'un exemple simple sur la façon de procéder, je viens d'écrire un substitut personnalisé qui convertit les erreurs, les expressions rationnelles et les fonctions en chaînes lisibles par l'homme ici .

21
mikermcneil

Pour les futurs utilisateurs cherchant 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 du JSON. stringify function pour éliminer les références circulaires. Voir un exemple de script sur https://Gist.github.com/4653128 .

La solution consiste essentiellement à conserver une référence à des 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 interdit également d’imprimer un objet deux fois, ce qui a notamment pour effet d’éviter les références circulaires.

Exemple d'emballage:

function stringifyOnce(obj, replacer, indent){
    var printedObjects = [];
    var printedObjectKeys = [];

    function printOnceReplacer(key, value){
        var printedObjIndex = false;
        printedObjects.forEach(function(obj, index){
            if(obj===value){
                printedObjIndex = index;
            }
        });

        if(printedObjIndex && typeof(value)=="object"){
            return "(see " + value.constructor.name.toLowerCase() + " with key " + printedObjectKeys[printedObjIndex] + ")";
        }else{
            var qualifiedKey = key || "(empty key)";
            printedObjects.Push(value);
            printedObjectKeys.Push(qualifiedKey);
            if(replacer){
                return replacer(key, value);
            }else{
                return value;
            }
        }
    }
    return JSON.stringify(obj, printOnceReplacer, indent);
}
12
Trindaz
var a={b:"b"};
a.a=a;
JSON.stringify(preventCircularJson(a));

évalue à:

"{"b":"b","a":"CIRCULAR_REFERENCE_REMOVED"}"

avec la fonction:

/**
 * Traverses a javascript object, and deletes all circular values
 * @param source object to remove circular references from
 * @param censoredMessage optional: what to put instead of censored values
 * @param censorTheseItems should be kept null, used in recursion
 * @returns {undefined}
 */
function preventCircularJson(source, censoredMessage, censorTheseItems) {
    //init recursive value if this is the first call
    censorTheseItems = censorTheseItems || [source];
    //default if none is specified
    censoredMessage = censoredMessage || "CIRCULAR_REFERENCE_REMOVED";
    //values that have allready apeared will be placed here:
    var recursiveItems = {};
    //initaite a censored clone to return back
    var ret = {};
    //traverse the object:
    for (var key in source) {
        var value = source[key]
        if (typeof value == "object") {
            //re-examine all complex children again later:
            recursiveItems[key] = value;
        } else {
            //simple values copied as is
            ret[key] = value;
        }
    }
    //create list of values to censor:
    var censorChildItems = [];
    for (var key in recursiveItems) {
        var value = source[key];
        //all complex child objects should not apear again in children:
        censorChildItems.Push(value);
    }
    //censor all circular values
    for (var key in recursiveItems) {
        var value = source[key];
        var censored = false;
        censorTheseItems.forEach(function (item) {
            if (item === value) {
                censored = true;
            }
        });
        if (censored) {
            //change circular values to this
            value = censoredMessage;
        } else {
            //recursion:
            value = preventCircularJson(value, censoredMessage, censorChildItems.concat(censorTheseItems));
        }
        ret[key] = value

    }

    return ret;
}
4
eshalev

Utilisez la méthode JSON.stringify avec un substitut. Lisez cette documentation pour plus d'informations. http://msdn.Microsoft.com/en-us/library/cc836459%28v=vs.94%29.aspx

var obj = {
  a: "foo",
  b: obj
}

var replacement = {"b":undefined};

alert(JSON.stringify(obj,replacement));

Trouvez un moyen de renseigner le tableau de remplacement avec des références cycliques. Vous pouvez utiliser la méthode typeof pour rechercher si la propriété est de type 'objet' (référence) et un contrôle d'égalité exact (===) pour vérifier la référence circulaire.

4
TWickz

Je sais que c’est une vieille question, mais je voudrais suggérer un paquetage NPM que j’ai créé et appelé smart-circular , qui fonctionne différemment des autres moyens proposés. C'est particulièrement utile si vous utilisez des objets volumineux et profonds

Certaines fonctionnalités sont:

  • Remplacement de références circulaires ou simplement de structures répétées à l'intérieur de l'objet par le chemin menant à sa première occurrence (pas seulement la chaîne [circular]);

  • En recherchant les circularités lors d'une recherche approfondie en largeur, le package garantit que ce chemin est aussi petit que possible, ce qui est important pour les objets très grands et profonds, où les chemins peuvent devenir ennuyeux et difficiles à suivre (le remplacement personnalisé JSON.stringify fait un DFS);

  • Permet des remplacements personnalisés, pratiques pour simplifier ou ignorer des 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.

3
Danilo Augusto

Je résous ce problème comme ceci:

var util = require('util');

// Our circular object
var obj = {foo: {bar: null}, a:{a:{a:{a:{a:{a:{a:{hi: 'Yo!'}}}}}}}};
obj.foo.bar = obj;

// Generate almost valid JS object definition code (typeof string)
var str = util.inspect(b, {depth: null});

// Fix code to the valid state (in this example it is not required, but my object was huge and complex, and I needed this for my case)
str = str
    .replace(/<Buffer[ \w\.]+>/ig, '"buffer"')
    .replace(/\[Function]/ig, 'function(){}')
    .replace(/\[Circular]/ig, '"Circular"')
    .replace(/\{ \[Function: ([\w]+)]/ig, '{ $1: function $1 () {},')
    .replace(/\[Function: ([\w]+)]/ig, 'function $1(){}')
    .replace(/(\w+): ([\w :]+GMT\+[\w \(\)]+),/ig, '$1: new Date("$2"),')
    .replace(/(\S+): ,/ig, '$1: null,');

// Create function to eval stringifyed code
var foo = new Function('return ' + str + ';');

// And have fun
console.log(JSON.stringify(foo(), null, 4));
1
MiF

Basé sur les autres réponses, je me retrouve avec le code suivant. Cela fonctionne plutôt bien avec des références circulaires, des objets avec des constructeurs personnalisés.

De l'objet donné à sérialiser, 

  • Cachez tous les objets que vous rencontrez lorsque vous les traversez et attribuez à chacun d'eux un hashID unique
  • Une fois qu'une référence circulaire est trouvée, marquez ce champ dans le nouvel objet comme circulaire et stockez le hashID de l'objet d'origine comme attribut.

Github Link - DecycledJSON

DJSHelper = {};
DJSHelper.Cache = [];
DJSHelper.currentHashID = 0;
DJSHelper.ReviveCache = [];

// DOES NOT SERIALIZE FUNCTION
function DJSNode(name, object, isRoot){
    this.name = name;
    // [ATTRIBUTES] contains the primitive fields of the Node
    this.attributes = {};

    // [CHILDREN] contains the Object/Typed fields of the Node
    // All [CHILDREN] must be of type [DJSNode]
    this.children = []; //Array of DJSNodes only

    // If [IS-ROOT] is true reset the Cache and currentHashId
    // before encoding
    isRoot = typeof isRoot === 'undefined'? true:isRoot;
    this.isRoot = isRoot;
    if(isRoot){
        DJSHelper.Cache = [];
        DJSHelper.currentHashID = 0;

        // CACHE THE ROOT
        object.hashID = DJSHelper.currentHashID++;
        DJSHelper.Cache.Push(object);
    }

    for(var a in object){
        if(object.hasOwnProperty(a)){
            var val = object[a];

            if (typeof val === 'object') {
                // IF OBJECT OR NULL REF.

                /***************************************************************************/
                // DO NOT REMOVE THE [FALSE] AS THAT WOULD RESET THE [DJSHELPER.CACHE]
                // AND THE RESULT WOULD BE STACK OVERFLOW
                /***************************************************************************/
                if(val !== null) {
                    if (DJSHelper.Cache.indexOf(val) === -1) {
                        // VAL NOT IN CACHE
                        // ADD THE VAL TO CACHE FIRST -> BEFORE DOING RECURSION
                        val.hashID = DJSHelper.currentHashID++;
                        //console.log("Assigned", val.hashID, "to", a);
                        DJSHelper.Cache.Push(val);

                        if (!(val instanceof Array)) {
                            // VAL NOT AN [ARRAY]
                            try {
                                this.children.Push(new DJSNode(a, val, false));
                            } catch (err) {
                                console.log(err.message, a);
                                throw err;
                            }
                        } else {
                            // VAL IS AN [ARRAY]
                            var node = new DJSNode(a, {
                                array: true,
                                hashID: val.hashID // HashID of array
                            }, false);
                            val.forEach(function (elem, index) {
                                node.children.Push(new DJSNode("elem", {val: elem}, false));
                            });
                            this.children.Push(node);
                        }
                    } else {
                        // VAL IN CACHE
                        // ADD A CYCLIC NODE WITH HASH-ID
                        this.children.Push(new DJSNode(a, {
                            cyclic: true,
                            hashID: val.hashID
                        }, false));
                    }
                }else{
                    // PUT NULL AS AN ATTRIBUTE
                    this.attributes[a] = 'null';
                }
            } else if (typeof val !== 'function') {
                // MUST BE A PRIMITIVE
                // ADD IT AS AN ATTRIBUTE
                this.attributes[a] = val;
            }
        }
    }

    if(isRoot){
        DJSHelper.Cache = null;
    }
    this.constructorName = object.constructor.name;
}
DJSNode.Revive = function (xmlNode, isRoot) {
    // Default value of [isRoot] is True
    isRoot = typeof isRoot === 'undefined'?true: isRoot;
    var root;
    if(isRoot){
        DJSHelper.ReviveCache = []; //Garbage Collect
    }
    if(window[xmlNode.constructorName].toString().indexOf('[native code]') > -1 ) {
        // yep, native in the browser
        if(xmlNode.constructorName == 'Object'){
            root = {};
        }else{
            return null;
        }
    }else {
        eval('root = new ' + xmlNode.constructorName + "()");
    }

    //CACHE ROOT INTO REVIVE-CACHE
    DJSHelper.ReviveCache[xmlNode.attributes.hashID] = root;

    for(var k in xmlNode.attributes){
        // PRIMITIVE OR NULL REF FIELDS
        if(xmlNode.attributes.hasOwnProperty(k)) {
            var a = xmlNode.attributes[k];
            if(a == 'null'){
                root[k] = null;
            }else {
                root[k] = a;
            }
        }
    }

    xmlNode.children.forEach(function (value) {
        // Each children is an [DJSNode]
        // [Array]s are stored as [DJSNode] with an positive Array attribute
        // So is value

        if(value.attributes.array){
            // ITS AN [ARRAY]
            root[value.name] = [];
            value.children.forEach(function (elem) {
                root[value.name].Push(elem.attributes.val);
            });
            //console.log("Caching", value.attributes.hashID);
            DJSHelper.ReviveCache[value.attributes.hashID] = root[value.name];
        }else if(!value.attributes.cyclic){
            // ITS AN [OBJECT]
            root[value.name] = DJSNode.Revive(value, false);
            //console.log("Caching", value.attributes.hashID);
            DJSHelper.ReviveCache[value.attributes.hashID] = root[value.name];
        }
    });

    // [SEPARATE ITERATION] TO MAKE SURE ALL POSSIBLE
    // [CYCLIC] REFERENCES ARE CACHED PROPERLY
    xmlNode.children.forEach(function (value) {
        // Each children is an [DJSNode]
        // [Array]s are stored as [DJSNode] with an positive Array attribute
        // So is value

        if(value.attributes.cyclic){
            // ITS AND [CYCLIC] REFERENCE
            root[value.name] = DJSHelper.ReviveCache[value.attributes.hashID];
        }
    });

    if(isRoot){
        DJSHelper.ReviveCache = null; //Garbage Collect
    }
    return root;
};

DecycledJSON = {};
DecycledJSON.stringify = function (obj) {
    return JSON.stringify(new DJSNode("root", obj));
};
DecycledJSON.parse = function (json, replacerObject) {
    // use the replacerObject to get the null values
    return DJSNode.Revive(JSON.parse(json));
};
DJS = DecycledJSON;

Exemple d'utilisation 1:

var obj = {
    id:201,
    box: {
        owner: null,
        key: 'storm'
    },
    lines:[
        'item1',
        23
    ]
};

console.log(obj); // ORIGINAL

// SERIALIZE AND THEN PARSE
var jsonObj = DJS.stringify(obj);
console.log(DJS.parse(jsonObj));

Exemple d'utilisation 2:

// PERSON OBJECT

function Person() {
    this.name = null;
    this.child = null;
    this.dad = null;
    this.mom = null;
}
var Dad = new Person();
Dad.name = 'John';
var Mom = new Person();
Mom.name = 'Sarah';
var Child = new Person();
Child.name = 'Kiddo';

Dad.child = Mom.child = Child;
Child.dad = Dad;
Child.mom = Mom;

console.log(Child); // ORIGINAL

// SERIALIZE AND THEN PARSE
var jsonChild = DJS.stringify(Child);
console.log(DJS.parse(jsonChild));
0
bytestorm

une autre solution pour résoudre ce problème avec ce type d’objets est l’utilisation de cette bibliothèque

https://github.com/ericmuyser/stringy

c'est simple et vous pouvez résoudre ce problème en quelques étapes simples.

0
Ehsan Aghaei

Bien que la réponse à cette question soit suffisante, vous pouvez également explicitement supprimer la propriété en question avant la chaîne de caractères à l’aide de l’opérateur delete.

delete obj.b; 
const jsonObject = JSON.stringify(obj);

opérateur de suppression

cela éliminera le besoin de créer ou de maintenir une logique complexe pour supprimer les références circulaires.

0
lachlan.p.jordan

Pour mettre à jour la réponse de substitution du fonctionnement de JSON (probablement pas recommandé, mais très simple), n'utilisez pas circular-json (c'est obsolète). Au lieu de cela, utilisez le successeur, plat:

https://www.npmjs.com/package/flatted

Emprunté à l'ancienne réponse ci-dessus auprès de @ user1541685, mais remplacé par la nouvelle:

npm i --save flatted

puis dans votre fichier js

const JSON = require('flatted');

...

const json = JSON.stringify(obj);

Tu pourrais aussi faire

const CircularJSON = require('flatted');

0
dylanh724
function myStringify(obj, maxDeepLevel = 2) {
  if (obj === null) {
    return 'null';
  }
  if (obj === undefined) {
    return 'undefined';
  }
  if (maxDeepLevel < 0 || typeof obj !== 'object') {
    return obj.toString();
  }
  return Object
    .entries(obj)
    .map(x => x[0] + ': ' + myStringify(x[1], maxDeepLevel - 1))
    .join('\r\n');
}
0
Sergey Gurin

Je sais que cette question est ancienne et a beaucoup de bonnes réponses mais je poste cette réponse à cause de sa nouvelle saveur (es5 +)  

Object.defineProperties(JSON, {
  refStringify: {
    value: function(obj) {

      let objMap = new Map();
      let stringified = JSON.stringify(obj,
        function(key, value) {

          // only for objects
          if (typeof value == 'object') {
            // If has the value then return a reference to it
            if (objMap.has(value))
              return objMap.get(value);

            objMap.set(value, `ref${objMap.size + 1}`);
          }
          return value;
        });
      return stringified;
    }
  },
  refParse: {
    value: function(str) {

      let parsed = JSON.parse(str);
      let objMap = _createObjectMap(parsed);
      objMap.forEach((value, key) => _replaceKeyWithObject(value, key));
      return parsed;
    }
  },
});

// *************************** Example
let a = {
  b: 32,
  c: {
    get a() {
        return a;
      },
      get c() {
        return a.c;
      }
  }
};
let stringified = JSON.refStringify(a);
let parsed = JSON.refParse(stringified, 2);
console.log(parsed, JSON.refStringify(parsed));
// *************************** /Example

// *************************** Helper
function _createObjectMap(obj) {

  let objMap = new Map();
  JSON.stringify(obj, (key, value) => {
    if (typeof value == 'object') {
      if (objMap.has(value))
        return objMap.get(value);
      objMap.set(value, `ref${objMap.size + 1}`);

    }
    return value;
  });
  return objMap;
}

function _replaceKeyWithObject(key, obj, replaceWithObject = obj) {

  Object.keys(obj).forEach(k => {

    let val = obj[k];
    if (val == key)
      return (obj[k] = replaceWithObject);
    if (typeof val == 'object' && val != replaceWithObject)
      _replaceKeyWithObject(key, val, replaceWithObject);
  });
}

0
Morteza Tourani

J'ai trouvé circular-json library sur github et cela a bien fonctionné pour mon problème.

Quelques fonctionnalités intéressantes que j'ai trouvées utiles:

  • Prend en charge l'utilisation multi-plate-forme mais je ne l'ai testé qu'avec node.js jusqu'à présent.
  • L'API est identique, il vous suffit donc de l'inclure et de l'utiliser en remplacement de JSON.
  • Il possède sa propre méthode d'analyse afin que vous puissiez reconvertir les données sérialisées 'circulaires' en objet.
0
JacopKane

Si 

console.log(JSON.stringify(object));

résulte en un 

TypeError: valeur d'objet cyclique

Ensuite, vous voudrez peut-être imprimer comme ceci:

var output = '';
for (property in object) {
  output += property + ': ' + object[property]+'; ';
}
console.log(output);
0
Thorsten Niehues

Essaye ça:

var obj = {
    a: "foo",
    b: obj
};

var circular_replacer = (value) => {
    var seen = [];
    if (value != null && typeof value == "object") {
        if (seen.indexOf(value) >= 0) return;
        seen.Push(value);
    }
    return value;
};

obj = circular_replacer(obj);
0
IamMHussain