itsource

순환 참조를 사용하여 JavaScript 개체 문자열 지정(JSON으로 변환)

mycopycode 2023. 2. 26. 09:45
반응형

순환 참조를 사용하여 JavaScript 개체 문자열 지정(JSON으로 변환)

순환 참조를 포함하는 JavaScript 개체 정의를 가지고 있습니다. 상위 개체를 참조하는 속성이 있습니다.

서버에 전달하고 싶지 않은 기능도 있습니다.이러한 오브젝트를 시리얼화 및 시리얼 해제하려면 어떻게 해야 합니까?

이것을 하는 가장 좋은 방법은 Douglas Crockford의 Stringify를 사용하는 것이라고 읽었습니다.그러나 Chrome에서 다음과 같은 오류가 발생합니다.

TypeError: 원형 구조를 JSON으로 변환하는 중

코드:

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

이것은 제가 이 질문을 위해 만든 테스트 케이스입니다.이 코드에는 오류가 있지만 기본적으로 개체 내에 개체가 있고 개체 생성 시 상위 개체가 무엇인지 보여주는 참조가 각 개체에 전달됩니다.각 오브젝트에는 함수도 포함되어 있기 때문에 문자열화하지 않습니다.나는 단지 다음과 같은 속성을 원한다.Person.Name.

서버에 송신하기 전에 시리얼화해, 같은 JSON이 반송되는 것을 전제로 해 시리얼화를 해제하려면 어떻게 해야 합니까?

원형 구조 오류는 개체 자체의 속성을 직접 가지고 있는 경우 발생합니다(a -> a 간접적으로 「 「」 「」)a -> b -> a를 참조해 주세요.

에러 메시지를 회피하려면 , 순환 참조가 발생했을 경우에 JSON.stringify 에 대처 방법을 지시합니다.예를 들어, 다른 사용자("상위")를 가리키는 사용자가 있는 경우, 원래 사용자를 가리킬 수도 있고 가리킬 수도 없는 경우 다음을 수행하십시오.

JSON.stringify( that.person, function( key, value) {
  if( key == 'parent') { return value.id;}
  else {return value;}
})

는 " " " 입니다.stringify필터 함수입니다.여기서는 참조된 오브젝트를 해당 ID로 변환하기만 하면 됩니다.단, 순환 참조를 해제하는 것은 자유롭게 할 수 있습니다.

위의 코드는 다음과 같이 테스트할 수 있습니다.

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

저는 다른 을 '어울리다', '어울리다', 어울리다'로 parent여러 언어(및 DOM)에서 사용되는 예약어이기 때문입니다.★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

립 없음

아래 리페이서를 사용하여 중복/원 참조된 개체에 대한 문자열 참조(json-path와 유사)를 가진 json을 생성합니다.

let s = JSON.stringify(obj, refReplacer());

function refReplacer() {
  let m = new Map(), v= new Map(), init = null;

  return function(field, value) {
    let p= m.get(this) + (Array.isArray(this) ? `[${field}]` : '.' + field); 
    let isComplex= value===Object(value)
    
    if (isComplex) m.set(value, p);  
    
    let pp = v.get(value)||'';
    let path = p.replace(/undefined\.\.?/,'');
    let val = pp ? `#REF:${pp[0]=='[' ? '$':'$.'}${pp}` : value;
    
    !init ? (init=value) : (val===init ? val="#REF:$" : 0);
    if(!pp && isComplex) v.set(value, path);
   
    return val;
  }
}




// ---------------
// TEST
// ---------------

// gen obj with duplicate references
let a = { a1: 1, a2: 2 };
let b = { b1: 3, b2: "4" };
let obj = { o1: { o2:  a  }, b, a }; // duplicate reference
a.a3 = [1,2,b];                      // circular reference
b.b3 = a;                            // circular reference


let s = JSON.stringify(obj, refReplacer(), 4);

console.log(s);

그리고 이러한 "ref-json"에서 객체를 재생성하는 파서 기능을 따라갑니다.

function parseRefJSON(json) {
  let objToPath = new Map();
  let pathToObj = new Map();
  let o = JSON.parse(json);
  
  let traverse = (parent, field) => {
    let obj = parent;
    let path = '#REF:$';

    if (field !== undefined) {
      obj = parent[field];
      path = objToPath.get(parent) + (Array.isArray(parent) ? `[${field}]` : `${field?'.'+field:''}`);
    }

    objToPath.set(obj, path);
    pathToObj.set(path, obj);
    
    let ref = pathToObj.get(obj);
    if (ref) parent[field] = ref;

    for (let f in obj) if (obj === Object(obj)) traverse(obj, f);
  }
  
  traverse(o);
  return o;
}



// ------------
// TEST
// ------------

let s = `{
    "o1": {
        "o2": {
            "a1": 1,
            "a2": 2,
            "a3": [
                1,
                2,
                {
                    "b1": 3,
                    "b2": "4",
                    "b3": "#REF:$.o1.o2"
                }
            ]
        }
    },
    "b": "#REF:$.o1.o2.a3[2]",
    "a": "#REF:$.o1.o2"
}`;

console.log('Open Chrome console to see nested fields:');
let obj = parseRefJSON(s);

console.log(obj);

dojo는 JSON에서 다음과 같은 형식으로 순환 참조를 나타낼 수 있습니다.{"id":"1","me":{"$ref":"1"}}

다음은 예를 제시하겠습니다.

http://jsfiddle.net/dumeG/

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

작성:

{
   "name":"Kris",
   "father":{
     "name":"Bill",
     "wife":{
          "name":"Karen"
      }
   },
   "mother":{
     "$ref":"#father.wife"
   }
}

주의: 이러한 순환 참조 오브젝트의 시리얼화를 해제하려면dojox.json.ref.fromJson방법.

기타 자원:

순환 참조가 있는 경우에도 DOM 노드를 JSON으로 시리얼화하려면 어떻게 해야 합니까?

JSON.stringify는 순환 참조를 나타낼 수 없습니다.

JSON에서 순환 참조를 처리할 수 있는 두 개의 적절한 모듈을 찾았습니다.

  1. CircularJSON https://github.com/WebReflection/circular-json. 출력은 .dll에 대한 입력으로 사용할 수 있습니다.브라우저 및 Node.js에서도 사용할 수 있습니다.또, 다음의 URL도 참조해 주세요.http://webreflection.blogspot.com.au/2013/03/solving-cycles-recursions-and-circulars.html
  2. Isaacs json-stringify-safe https://github.com/isaacs/json-stringify-safe은 가독성이 향상될 수 있지만 .vl에서는 사용할 수 없으며 Node.js에서만 사용할 수 있습니다.

어느 쪽이든 고객의 요구를 만족시킬 수 있습니다.

리모트 디버깅을 할 수 없었기 때문에 복잡한 오브젝트를 페이지에 기록해야 했기 때문에 이 스레드가 발생하였습니다.Douglas Crockford(JSON의 inceptor) 자신의 cycle.js를 찾았습니다.이것은, 구문 분석 후에 다시 접속할 수 있도록, 문자열등의 순환 참조에 주석을 붙입니다.사이클 해제된 딥 복사는 JSON.stringify를 통과해도 안전합니다.맛있게 드세요!

https://github.com/douglascrockford/JSON-js

cycle.cycle:이 파일에는 JSON.decycle과 JSON.retrocycle의 2가지 함수가 포함되어 있으며, 이를 통해 JSON에서 순환 구조 및 대그를 인코딩한 후 복구할 수 있습니다.이는 ES5에서는 제공되지 않는 기능입니다.JSONPath는 링크를 나타내기 위해 사용됩니다.

순환 참조를 제거하기 위해 다음을 사용했습니다.

JS.dropClasses = function(o) {

    for (var p in o) {
        if (o[p] instanceof jQuery || o[p] instanceof HTMLElement) {
            o[p] = null;
        }    
        else if (typeof o[p] == 'object' )
            JS.dropClasses(o[p]);
    }
};

JSON.stringify(JS.dropClasses(e));

언급URL : https://stackoverflow.com/questions/10392293/stringify-convert-to-json-a-javascript-object-with-circular-reference

반응형