当前位置: 首页 > 知识库问答 >
问题:

Stringify(转换为JSON)具有循环引用的JavaScript对象

叶富
2023-03-14

我有一个包含循环引用的JavaScript对象定义:它有一个引用父对象的属性。

它还有一些我不想传递给服务器的函数。如何序列化和反序列化这些对象?

我读过这样做的最好方法是使用Douglas Crockford的stringify。但是,我在Chrome中遇到以下错误:

将圆形结构转换为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这样的属性。名称

如何在发送到服务器之前序列化并反序列化它,假设相同的JSON被传回?

共有3个答案

苏承载
2023-03-14

使用下面的替换程序生成带有字符串引用(类似json路径)的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);
慕麒
2023-03-14

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不能表示循环引用

盛浩阔
2023-03-14

循环结构错误发生时,你有一个属性的对象,这是直接的对象本身(a-

要避免错误消息,请告诉JSON。字符串化遇到循环引用时的操作。例如,如果您有一个人指向另一个人(“家长”),而该人可能(也可能不)指向原始人,请执行以下操作:

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)中都是保留字。这往往会造成混乱的道路上。。。

 类似资料:
  • 问题内容: 我有一个包含循环引用的JavaScript对象定义:它具有一个引用父对象的属性。 它还具有一些我不想传递给服务器的功能。我将如何序列化和反序列化这些对象? 我读过,做到这一点的最好方法是使用道格拉斯·克罗克福德的stringify。但是,我在Chrome中遇到以下错误: TypeError:将圆形结构转换为JSON 编码: 这是我为这个问题创建的测试用例。这段代码中有错误,但是本质上我

  • 问题内容: 如果我从json.net获得序列化的JSON,如下所示: 我想让淘汰赛在FooList上输出foreach,但是我不确定如何继续,因为$ ref东西可能会抛出东西。 我在想解决方案将以某种方式通过不使用以下方式强制将所有Foos呈现在FooList中: 但这似乎很浪费。 问题答案: 从服务器接收的json对象包含循环引用。在使用对象之前,您必须首先 从对象中删除所有属性,这意味着`$r

  • 问题内容: 因此,我得到了以下javascript,其中包含键/值对,用于将嵌套路径映射到目录。 现在,我要做的是根据地图中的键创建一个JSON对象。 它一定要是, 不知道是否有开箱即用的方式来执行此操作。任何帮助表示赞赏。 问题答案: 您可以在地图和键上循环并分配值

  • 问题内容: 我有一个从包含重复密钥的数据库中获取的JSON字符串。我想通过将重复键的值组合到数组中来删除重复键。 例如 输入项 输出量 实际数据是一个可能嵌套的大文件。我不会提前知道有多少对。 我需要为此使用Java。org.json由于重复的键而引发异常,gson可以解析该字符串,但是每个重复的键都会覆盖最后一个。我需要保留所有数据。 如果可能的话,我想不编辑任何库代码就这样做 问题答案: 从今

  • 问题内容: 我定义了两个类,以便它们都包含对另一个对象的引用。它们看起来与此类似(这是简化的;在我的实际域模型中,类A包含一个B列表,每个B都有对父A的引用): 在与已通过使用Eclipse中A和B这两个问题的两个场产生的是调用或在任一对象方法的结果在因为它们都调用另一个对象的和方法。例如,以下程序将无法使用上述对象: 如果用这种方式用循环关系定义域模型存在内在的错误,请告诉我。据我所知,虽然这是

  • 由于几个循环引用,我遇到了通过GoogleGSON序列化Java对象的问题。我的所有尝试都以StackOverflowException结束,因为GSON无法处理这些循环引用。 作为一个解决方案,我发现了以下: http://code.google.com/p/google-gson/source/browse/trunk/extras/src/main/java/com/google/gson/