순환 참조를 사용하여 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;
};
});
BTW, parent
여러 언어 (및 DOM)에서 예약어이므로 " "에 대해 다른 속성 이름을 선택합니다 . 이것은 길을 혼란스럽게 만드는 경향이 있습니다 ...
것으로 보인다 도장이 형태로 JSON에 순환 참조를 나타낼 수 있습니다 :{"id":"1","me":{"$ref":"1"}}
다음은 그 예입니다.
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);
});
Produces:
{
"name":"Kris",
"father":{
"name":"Bill",
"wife":{
"name":"Karen"
}
},
"mother":{
"$ref":"#father.wife"
}
}
Note: You can also de-serialize these circular referenced objects using the dojox.json.ref.fromJson
method.
Other Resources:
How to serialize DOM node to JSON even if there are circular references?
JSON.stringify can't represent circular references
I found two suitable modules to handle circular references in JSON.
- CircularJSON https://github.com/WebReflection/circular-json whose output can be used as input to .parse(). It also works in Browsers & Node.js Also see: http://webreflection.blogspot.com.au/2013/03/solving-cycles-recursions-and-circulars.html
- Isaacs json-stringify-safe https://github.com/isaacs/json-stringify-safe which maybe more readable but can't be used for .parse and is only available for Node.js
Either of these should meet your needs.
Happened upon this thread because I needed to log complex objects to a page, since remote debugging wasn't possible in my particular situation. Found Douglas Crockford's (inceptor of JSON) own cycle.js, which annotates circular references as strings such that they can be reconnected after parsing. The de-cycled deep copy is safe to pass through JSON.stringify. Enjoy!
https://github.com/douglascrockford/JSON-js
cycle.js: This file contains two functions, JSON.decycle and JSON.retrocycle, which make it possible to encode cyclical structures and dags in JSON, and to then recover them. This is a capability that is not provided by ES5. JSONPath is used to represent the links.
I used the following to eliminate the circular references:
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));
'Nice programing' 카테고리의 다른 글
이메일 주소를 사용자 ID로 사용할 때의 장단점은 무엇입니까? (0) | 2020.11.11 |
---|---|
추상 클래스 vs. 인터페이스 vs. 믹스 인 (0) | 2020.11.11 |
셸에서 셀러리 주기적 작업을 수동으로 실행하려면 어떻게해야합니까? (0) | 2020.11.11 |
“RangeError : 최대 호출 스택 크기를 초과했습니다.”이유는 무엇입니까? (0) | 2020.11.11 |
TriviallyCopyable이 아닌 객체에 대해 std :: memcpy의 동작이 정의되지 않은 이유는 무엇입니까? (0) | 2020.11.11 |