program tip

JSON과 유사한 형식으로 원형 구조를 인쇄하려면 어떻게해야합니까?

radiobox 2020. 10. 3. 10:26
반응형

JSON과 유사한 형식으로 원형 구조를 인쇄하려면 어떻게해야합니까?


JSON으로 변환하여 보내려는 큰 개체가 있습니다. 그러나 그것은 원형 구조를 가지고 있습니다. 나는 순환 참조가 존재하는 모든 것을 던지고 문자열이 될 수있는 것을 보내고 싶습니다. 어떻게하나요?

감사.

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

obj를 다음과 같이 문자열 화하고 싶습니다.

{"a":"foo"}

JSON.stringify사용자 지정 대체물과 함께 사용하십시오 . 예를 들면 :

// 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, discard key
            return;
        }
        // Store value in our collection
        cache.push(value);
    }
    return value;
});
cache = null; // Enable garbage collection

이 예에서 대체자는 100 % 정확하지 않습니다 ( "duplicate"정의에 따라 다름). 다음과 같은 경우 값이 삭제됩니다.

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

그러나 개념은 다음과 같습니다. 사용자 지정 대체자를 사용하고 구문 분석 된 개체 값을 추적합니다.


Node.js에서는 util.inspect (object)를 사용할 수 있습니다 . 원형 링크를 "[Circular]"로 자동 대체합니다.


내장되어 있지만 (설치할 필요 없음) 가져와야합니다.

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



아래 댓글 작성자에게 칭찬을 해주세요 ...


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

보이는 값은 배열이 아닌 set에 저장되어야하며 (replacer는 모든 요소에서 호출 ) 순환 참조로 이어지는 체인의 JSON.stringify 각 요소 를 시도 할 필요가 없습니다 .

허용되는 답변과 마찬가지로이 솔루션은 순환 값 뿐만 아니라 모든 반복 값을 제거 합니다. 그러나 적어도 기하 급수적 인 복잡성은 없습니다.


그냥 해

npm i --save circular-json

그런 다음 js 파일에서

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

당신은 또한 할 수 있습니다

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

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

참고 :이 패키지와 관련이 없습니다. 하지만 이것을 위해 사용합니다.


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

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

JSON.decycleDouglas Crockford가 구현 한 방법 도 있습니다 . 그의 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 fork 참조 ). 이것은 잘 작동합니다.

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

내 포크 JSON.decycle(variable)에서 원본과 같이 작동하며 variableDOM 노드 / 요소 포함 된 경우 예외가 발생합니다 .

사용할 때 JSON.decycle(variable, true)결과를 되돌릴 수 없다는 사실을 받아들입니다 (재사용은 DOM 노드를 다시 만들지 않음). 그러나 DOM 요소는 어느 정도 식별 가능해야합니다. 예를 들어 div요소에 ID가 있으면 문자열로 대체됩니다 "div#id-of-the-element".


@isaacs에서 json-stringify-safe확인하는 것이 좋습니다 . NPM에서 사용됩니다.

BTW- Node.js를 사용하지 않는 경우 소스 코드관련 부분 에서 4-27 행을 복사하여 붙여 넣을 수 있습니다 .

설치하기 위해서:

$ 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]'
}

@Rob W에서 언급 한 바닐라 JSON.stringify 함수와 마찬가지로 "replacer"함수를에 두 번째 인수로 전달하여 삭제 동작을 사용자 지정할 수도 있습니다 stringify(). 당신은 자신이 작업을 수행하는 방법에 대한 간단한 예를 필요로 발견하면, 난 그냥 사람이 읽을 수있는 문자열로 오류, regexps '에, 그리고 기능을 강제 변환 사용자 정의 대용품 썼다 여기를 .


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

해결책은 본질적으로 이전에 인쇄 된 객체에 대한 참조를 배열에 유지하고 값을 반환하기 전에 replacer 함수에서 확인하는 것으로 요약됩니다. 순환 참조를 배제하는 것보다 더 제한적입니다. 왜냐하면 객체를 두 번 인쇄하는 것도 배제하기 때문입니다. 그 측면에서 영향을 미치는 부분 중 하나는 순환 참조를 피하는 것입니다.

래퍼 예 :

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

대체자와 함께 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 메서드를 사용하여 속성의 유형이 'object'(reference)인지 확인하고 정확한 동등성 검사 (===)를 사용하여 순환 참조를 확인할 수 있습니다.


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

나는 이것이 오래된 질문이라는 것을 알고 있지만 제안 된 다른 방법과 다르게 작동하는 smart-circular 라는 NPM 패키지를 제안하고 싶습니다 . 크고 깊은 물체를 사용하는 경우 특히 유용 합니다 .

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

  • 객체 내부의 순환 참조 또는 단순히 반복되는 구조를 첫 번째 발생으로 이어지는 경로로 대체합니다 (단지 [circular] 문자열이 아님 ).

  • 폭 우선 검색에서 순환 성을 찾아 패키지는이 경로가 가능한 한 작은 지 확인합니다. 이는 경로가 성가 시게 길어지고 따라 가기 어려울 수있는 매우 크고 깊은 개체를 처리 할 때 중요합니다. JSON.stringify는 DFS를 수행합니다.

  • 개체의 덜 중요한 부분을 단순화하거나 무시하는 데 편리한 개인 교체를 허용합니다.

  • 마지막으로, 참조 된 필드에 액세스하는 데 필요한 방식으로 경로가 정확하게 작성되므로 디버깅에 도움이 될 수 있습니다.


만약

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

결과

TypeError : 순환 객체 값

그런 다음 다음과 같이 인쇄 할 수 있습니다.

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

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의 개체 정의는 최신 Chrome 또는 Firefox에서 순환 참조 오류를 발생시키지 않습니다. 이 때문에이 답변의 정의를 수정 오류가 발생.



github 에서 Circular-json 라이브러리를 찾았 으며 내 문제에 대해 잘 작동했습니다.

유용하다고 생각되는 몇 가지 좋은 기능

  • 다중 플랫폼 사용을 지원하지만 지금까지 node.js로만 테스트했습니다.
  • API는 동일하므로 JSON 대체물로 포함하고 사용하기 만하면됩니다.
  • 자체 구문 분석 방법이 있으므로 '순환'직렬화 된 데이터를 다시 객체로 변환 할 수 있습니다.

이 문제를 다음과 같이 해결합니다.

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

이 질문이 오래되고 훌륭한 답변이 많이 있다는 것을 알고 있지만 새로운 맛 때문에이 답변을 게시합니다 (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);
  });
}


이것에 대한 충분한 답이 있었지만 delete연산자를 사용하여 문자열 화하기 전에 해당 속성을 명시 적으로 삭제할 수도 있습니다 .

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

연산자 삭제

이렇게하면 순환 참조를 제거하기 위해 복잡한 논리를 만들거나 유지할 필요가 없습니다.


이러한 종류의 개체에서이 문제를 해결하기위한 다른 해결책은이 라이브러리를 사용하는 것입니다.

https://github.com/ericmuyser/stringy

간단하고 몇 가지 간단한 단계로이 문제를 해결할 수 있습니다.


다른 답변에 따라 다음 코드로 끝납니다. 순환 참조, 사용자 지정 생성자가있는 개체와 잘 작동합니다.

직렬화 할 주어진 객체에서

  • 개체를 순회하는 동안 발견 한 모든 개체를 캐시하고 각 개체에 고유 한 해시 ID를 할당합니다 (자동 증가 번호도 작동 함).
  • 순환 참조가 발견되면 새 객체의 해당 필드를 순환으로 표시하고 원래 객체의 해시 ID를 속성으로 저장합니다.

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

이 시도:

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

JSON 작동 방식을 재정의하는 대답을 업데이트하려면 (권장되지는 않지만 매우 간단합니다) 사용하지 마십시오 (사용 circular-json되지 않음). 대신 다음과 같이 평면화 된 후속 작업을 사용하십시오.

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

@ user1541685에서 위의 이전 답변에서 빌 렸지만 새 답변으로 대체되었습니다.

npm i --save flatted

그런 다음 js 파일에서

const JSON = require('flatted');

...

const json = JSON.stringify(obj);

당신은 또한 할 수 있습니다

const CircularJSON = require('flatted');


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

참고 URL : https://stackoverflow.com/questions/11616630/how-can-i-print-a-circular-structure-in-a-json-like-format

반응형