복붙노트

[NODEJS] 어떻게 JSON과 같은 형식으로 원형 구조를 인쇄 할 수 있습니까?

NODEJS

어떻게 JSON과 같은 형식으로 원형 구조를 인쇄 할 수 있습니까?

해결법


  1. 1.사용자 정의 대용품으로 JSON.stringify를 사용합니다. 예를 들면 :

    사용자 정의 대용품으로 JSON.stringify를 사용합니다. 예를 들면 :

    // Demo: Circular reference
    var circ = {};
    circ.circ = circ;
    
    // Note: cache should not be re-used by repeated calls to JSON.stringify.
    var cache = [];
    JSON.stringify(circ, (key, value) => {
      if (typeof value === 'object' && value !== null) {
        // Duplicate reference found, discard key
        if (cache.includes(value)) return;
    
        // Store value in our collection
        cache.push(value);
      }
      return value;
    });
    cache = null; // Enable garbage collection
    

    이 예에서 대체물은 100 % 정확한 ( "복제"의 당신의 정의에 따라)되지 않습니다. 다음의 경우에, 값은 폐기된다 :

    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, ...);
    

    구문 분석 된 개체 값의 사용자 지정 대용품 및 킵 트랙을 사용 :하지만 개념은 의미합니다.

    ES6로 작성된 유틸리티 함수로 :

    // safely handles circular references
    JSON.safeStringify = (obj, indent = 2) => {
      let cache = [];
      const retVal = JSON.stringify(
        obj,
        (key, value) =>
          typeof value === "object" && value !== null
            ? cache.includes(value)
              ? undefined // Duplicate reference found, discard key
              : cache.push(value) && value // Store value in our collection
            : value,
        indent
      );
      cache = null;
      return retVal;
    };
    
    // Example:
    console.log('options', JSON.safeStringify(options))
    

  2. 2.Node.js를, 당신은 util.inspect (객체)를 사용할 수 있습니다. 그것은 자동으로 "[원형]"원형 링크를 대체합니다.

    Node.js를, 당신은 util.inspect (객체)를 사용할 수 있습니다. 그것은 자동으로 "[원형]"원형 링크를 대체합니다.

    내장 된 (더 설치가 필요하지 않습니다) 임에도 불구하고, 당신은 그것을 가져와야합니다

    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))
    

    또한 옵션 (위 링크 참조) 검사 할 개체를 전달할 수 있다는 인식

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

    읽고 아래에 덧글로 명성을주십시오 ...


  3. 3.아직 아무도 MDN 페이지에서 적절한 솔루션을 게시되지 왜 궁금해 ...

    아직 아무도 MDN 페이지에서 적절한 솔루션을 게시되지 왜 궁금해 ...

    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());
    

    신 값하지 어레이, 세트에 저장한다 (대체물이 모든 요소에 호출된다) 원형 기준으로 이어지는 체인 JSON.stringify 각 요소를 시도 할 필요가 없다.

    허용 대답에서와 마찬가지로,이 솔루션은 모든 반복 값뿐만 아니라 원형 사람을 제거합니다. 그러나 적어도 그것은 지수의 복잡성이 없습니다.


  4. 4.그냥 해

    그냥 해

    npm i --save circular-json
    

    다음의 js 파일에

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

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

    참고 :이 패키지와는 아무 상관이 없습니다. 하지만이 그것을 사용합니까.

    참고 CircularJSON 단지 및 반음 내린 그 후속 인 유지 보수에하시기 바랍니다.


  5. 5.정말 Trindaz의 솔루션을 좋아 - 더 자세한, 그러나 그것은 몇 가지 버그를했다. 나도 그것을 좋아 누구든지 그들을 고정.

    정말 Trindaz의 솔루션을 좋아 - 더 자세한, 그러나 그것은 몇 가지 버그를했다. 나도 그것을 좋아 누구든지 그들을 고정.

    게다가, 내 캐시 개체에 대한 길이 제한을 추가했다.

    내가 인쇄하고있는 객체가 정말 큰 경우 - 나는 무한히 큰 의미 - 내 알고리즘을 제한합니다.

    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);
    };
    

  6. 6.또한 더글러스 크록 포드에 의해 구현 된 JSON.decycle의 방법이 있습니다. 자신을 참조하십시오 cycle.js. 이것은 거의 모든 표준 구조를 캐릭터 라인 화 할 수 있습니다 :

    또한 더글러스 크록 포드에 의해 구현 된 JSON.decycle의 방법이 있습니다. 자신을 참조하십시오 cycle.js. 이것은 거의 모든 표준 구조를 캐릭터 라인 화 할 수 있습니다 :

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

    또한 retrocycle 방법으로 원래 개체를 다시 만들 수 있습니다. 당신이 객체에서 사이클을 제거 할 필요는 없습니다 그래서 그 캐릭터 라인 화합니다.

    그러나 이것은 (실제 사용 사례에서 사이클의 일반적인 원인) DOM 노드에 대해 작동하지 않습니다. 예를 들어이 발생합니다 :

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

    나는 (내 cycle.js 포크 참조) 그 문제를 해결하기 위해 포크를했습니다. 이것은 잘 작동합니다 :

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

    주 내 포크 JSON.decycle (변수)에 원래 같이 작동 변수가 DOM 노드 / 요소를 포함 할 경우 예외를 던질 것입니다.

    당신이 JSON.decycle (사실 변수)를 사용하면이 결과는 되돌릴 수 없을 것이라는 사실을 (retrocycle는 DOM 노드를 다시 만듭니다되지 않습니다) 동의합니다. DOM 요소 비록 어느 정도 식별해야한다. div 요소는 다음 아이디가있는 경우 예를 들어, 그것은 문자열 "DIV # 아이디 -의 요소"로 대체됩니다.


  7. 7.RobW의 대답 @ 정확하지만,이 더 성능이 좋은입니다! 그것은 해시 맵 / 세트를 사용하기 때문에 :

    RobW의 대답 @ 정확하지만,이 더 성능이 좋은입니다! 그것은 해시 맵 / 세트를 사용하기 때문에 :

    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;
      });
    };
    

  8. 8.나는 @ isaacs--는 NPM에 사용되는에서 JSON-캐릭터 라인 화 안전을 확인하는 것이 좋습니다 것입니다.

    나는 @ isaacs--는 NPM에 사용되는에서 JSON-캐릭터 라인 화 안전을 확인하는 것이 좋습니다 것입니다.

    설치하기 위해서:

    $ npm install json-stringify-safe --save
    

    쓰다:

    // 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));
    

    이 수율 :

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

  9. 9.이 문제에 대한 해결책을 찾고 미래 명의 Google은 모든 순환 참조의 열쇠를 모를 때를 들어, 순환 참조를 배제하기 위해 JSON.stringify 기능 래퍼를 사용할 수 있습니다. https://gist.github.com/4653128에서 예제 스크립트를 참조하십시오.

    이 문제에 대한 해결책을 찾고 미래 명의 Google은 모든 순환 참조의 열쇠를 모를 때를 들어, 순환 참조를 배제하기 위해 JSON.stringify 기능 래퍼를 사용할 수 있습니다. https://gist.github.com/4653128에서 예제 스크립트를 참조하십시오.

    이 용액은 본질적으로 배열 이전에 인쇄 된 객체에 대한 참조를 유지하고 값을 리턴하기 전에 대체물 함수 것을 확인 귀결. 그것은 또한 어느 객체를 인쇄 배제하기 때문에 두 번, 측면 중 하나가있는 순환 참조를 방지하는 것입니다 영향을, 단지 순환 참조를 배제 이상의 협착입니다.

    예 래퍼 :

    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);
    }
    

  10. 10.대용품으로 JSON.stringify 방법을 사용합니다. 자세한 내용은이 문서를 참조하십시오. http://msdn.microsoft.com/en-us/library/cc836459%28v=vs.94%29.aspx

    대용품으로 JSON.stringify 방법을 사용합니다. 자세한 내용은이 문서를 참조하십시오. 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));
    

    순환 참조가 교체 배열을 채울 수있는 방법을 그림. 당신은 재산 유형 '객체'(참조)와 순환 참조를 확인하기 위해 정확한 평등 검사 (===) 인 경우 찾기 위해 대한 typeof 방법을 사용할 수 있습니다.


  11. 11.만약

    만약

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

    A의 결과

    그럼 당신은 다음과 같이 인쇄 할 수 있습니다 :

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

  12. 12.

    var a={b:"b"};
    a.a=a;
    JSON.stringify(preventCircularJson(a));
    

    들을 평가하기 :

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

    기능을 가진 :

    /**
     * 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;
    }
    

  13. 13.나는이 오래된 질문이다 알지만, 제안 다른 방법에서 다르게 작동 내가 스마트 원형이라고 만든 NPM 패키지를 제안하고 싶습니다. 당신이 크고 깊은 객체를 사용하는 경우 그것은 특별히 유용하다.

    나는이 오래된 질문이다 알지만, 제안 다른 방법에서 다르게 작동 내가 스마트 원형이라고 만든 NPM 패키지를 제안하고 싶습니다. 당신이 크고 깊은 객체를 사용하는 경우 그것은 특별히 유용하다.

    일부 기능은 다음과 같습니다 :


  14. 14.JSON.stringify ()에 두 번째 인수는 또한 당신이 당신의 데이터 내에서 발생하는 모든 객체에서 보존되어야 키 이름의 배열을 지정할 수 있습니다. 이것은 모든 사용 사례 작동하지 않을 수 있습니다,하지만 훨씬 간단 솔루션입니다.

    JSON.stringify ()에 두 번째 인수는 또한 당신이 당신의 데이터 내에서 발생하는 모든 객체에서 보존되어야 키 이름의 배열을 지정할 수 있습니다. 이것은 모든 사용 사례 작동하지 않을 수 있습니다,하지만 훨씬 간단 솔루션입니다.

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify

    var obj = {
        a: "foo",
        b: this
    }
    
    var json = JSON.stringify(obj, ['a']);
    console.log(json);
    // {"a":"foo"}
    

    참고 : 이상하게도, OP에서 개체 정의가 최신 크롬이나 파이어 폭스에서 순환 참조 오류가 발생하지 않습니다. 이 오류가 발생했습니다 있도록이 답변의 정의가 수정되었습니다.


  15. 15.JSON이 작동하는 방식을 재정의 답을 업데이트하려면 (아마하지 않는 것이 좋습니다,하지만 매우 간단), (이되지 않는 것) 원형 JSON을 사용하지 마십시오. 대신, 후계자를 사용 반음 :

    JSON이 작동하는 방식을 재정의 답을 업데이트하려면 (아마하지 않는 것이 좋습니다,하지만 매우 간단), (이되지 않는 것) 원형 JSON을 사용하지 마십시오. 대신, 후계자를 사용 반음 :

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

    @ user1541685에서 이전 대답은 위에서 차용하지만, 새 것으로 교체 :

    NPM 내가 --save 플랫

    다음의 js 파일에

    const CircularJSON = require('flatted');
    const json = CircularJSON.stringify(obj);
    

  16. 16.나는 GitHub의에 원형 JSON 라이브러리를 발견하고 내 문제 잘했다.

    나는 GitHub의에 원형 JSON 라이브러리를 발견하고 내 문제 잘했다.

    좋은 내가 유용하다고 기능 :


  17. 17.이 같은이 문제를 해결 :

    이 같은이 문제를 해결 :

    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));
    

  18. 18.이 질문은 오래되어 큰 응답을 많이 가지고 알고 있지만, 새로운 맛의의 때문에 나는이 대답을 게시 (ES5 +)

    이 질문은 오래되어 큰 응답을 많이 가지고 알고 있지만, 새로운 맛의의 때문에 나는이 대답을 게시 (ES5 +)

    Object.defineProperties (JSON, { refStringify : { 값 : 함수 (OBJ) { ) (objMap = 새로운지도를 보자; ,도 캐릭터 라인 = JSON.stringify (OBJ하자 함수 (키 값) { //에만 개체에 대한 만약 {( '객체 == 값 대해서 typeof) // 만약이 값이 다음에 대한 참조를 반환있다 경우 (objMap.has (값)) 창 objMap.get (값); objMap.set (값 '심판 $ {} objMap.size + 1'); } 값을 반환; }); 도 캐릭터 라인 반환; } }, refParse : { 값 : 함수 (STR) { 구문 분석 = JSON.parse (STR)를 보자; 하자 objMap = _createObjectMap (구문 분석); objMap.forEach ((값, 키) => _replaceKeyWithObject (값, 키)); 반환 구문 분석; } }, }); // *************************** 예 {A =하자 B : 32 씨: { 도착() { 를 반환; }, () {C를 얻을 A.C를 반환; } } }; 하자도 캐릭터 라인 = JSON.refStringify (A); 파싱 ​​= JSON.refParse하자 (도 캐릭터 라인, 2); CONSOLE.LOG (파싱 JSON.refStringify (파싱)); // *************************** /예 // *************************** 도우미 함수 _createObjectMap (OBJ) { ) (objMap = 새로운지도를 보자; JSON.stringify (OBJ (키 값) => { 만약 {( '객체 == 값 대해서 typeof) 경우 (objMap.has (값)) 창 objMap.get (값); objMap.set (값 '심판 $ {} objMap.size + 1'); } 값을 반환; }); objMap 반환; } 함수 _replaceKeyWithObject (키 OBJ, replaceWithObject = OBJ) { Object.keys (OBJ) .forEach (K => { 브로 = OBJ [K]를 보자; 경우 (발 == 키) 창 (OBJ [K] = replaceWithObject); 경우 (대해서 typeof 브로 == '물체'브로 &&! = replaceWithObject) _replaceKeyWithObject (키, 발, replaceWithObject); }); }


  19. 19.이 충분히 답했지만, 당신은 명시 적으로 delete 연산자를 사용하여 문자열 화 (stringification)하기 전에 문제의 속성을 삭제할 수 있습니다.

    이 충분히 답했지만, 당신은 명시 적으로 delete 연산자를 사용하여 문자열 화 (stringification)하기 전에 문제의 속성을 삭제할 수 있습니다.

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

    delete 연산자

    이 구축하거나 순환 참조를 제거하기 위해 복잡한 로직을 유지할 필요가 제거됩니다.


  20. 20.

    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');
    }
    

  21. 21.개체의 이러한 종류의이 문제를 해결하기위한 다른 해결책은이 라이브러리를 사용하고 있습니다

    개체의 이러한 종류의이 문제를 해결하기위한 다른 해결책은이 라이브러리를 사용하고 있습니다

    https://github.com/ericmuyser/stringy

    간단한 당신은 몇 가지 간단한 단계에서이 문제를 해결할 수 있습니다.


  22. 22.다른 답변을 바탕으로 다음 코드와 끝까지. 그것은 사용자 정의 생성자와 객체, 순환 참조와 꽤 잘 작동합니다.

    다른 답변을 바탕으로 다음 코드와 끝까지. 그것은 사용자 정의 생성자와 객체, 순환 참조와 꽤 잘 작동합니다.

    주어진 객체 직렬화에서,

    Github에서 링크 - 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;
    

    예제 구문 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));
    

    사용 예 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));
    

  23. 23.이 시도:

    이 시도:

    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);
    

  24. 24.당신은 JSON 파서 라이브러리를 시도해 볼 수도 있습니다 : treedoc합니다. 그것은 순환 참조를 지원하고 또한 참조로 반복 객체 dedupes.

    당신은 JSON 파서 라이브러리를 시도해 볼 수도 있습니다 : treedoc합니다. 그것은 순환 참조를 지원하고 또한 참조로 반복 객체 dedupes.

    원사 추가 treedoc

    import {TD} from 'treedoc'
    TD.stringify(obj);
    

    당신은 더 많은 사용자 정의를 원하는 경우

    import {TD, TDEncodeOption} from 'treedoc'
    
    const opt = new TDEncodeOption();
    opt.coderOption.setShowType(true).setShowFunction(true);
    opt.jsonOption.setIndentFactor(2);
    return TD.stringify(obj, opt);
    

    생성 JSON 파일 JSON 노드 레퍼런스를 통해 네비게이션을 지원 http://treedoc.org 시청자에 의해 시청 될 수있다.

    [뻔뻔한 플러그] 내가이 라이브러리의 저자 해요

  25. from https://stackoverflow.com/questions/11616630/how-can-i-print-a-circular-structure-in-a-json-like-format by cc-by-sa and MIT license