Stringify (преобразование в JSON) объект JavaScript с круговой ссылкой


у меня есть определение объекта JavaScript, которое содержит циклическую ссылку: у него есть свойство, которое ссылается на родительский объект.

Он также имеет функции, которые я не хочу передавать на сервер. Как бы я сериализовал и десериализовал эти объекты?

Я читал, что лучший способ сделать это-использовать 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 передается обратно?

5 55

5 ответов:

кольцевой структуры ошибка возникает, когда у вас есть свойство объекта, сам объект напрямую (a -> a) или косвенно (a -> b -> a).

чтобы избежать сообщения об ошибке, сообщите JSON.stringify, что делать, когда он сталкивается с круговой ссылкой. Например, если у вас есть человек, указывающий на другого человека ("родителя"), который может (или не может) указывать на оригинального человека, выполните следующие действия:

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

второй параметр stringify - это фильтр. Здесь он просто преобразует указанный объект в его идентификатор, но вы можете делать все, что хотите, чтобы разорвать круговую ссылку.

вы можете проверить приведенный выше код следующим образом:

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 в виде : {"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 выход которого можно использовать как входной сигнал к.разбор.)( Он также работает в браузерах и узлах.js Также см.: 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 который может быть более читаемый, но не может быть использован для .разбор и доступен только для узла.js

любой из них должен удовлетворить ваши потребности.

произошло в этом потоке, потому что мне нужно было регистрировать сложные объекты на странице, так как удаленная отладка была невозможна в моей конкретной ситуации. Нашел собственный цикл Дугласа Крокфорда (inceptor of JSON).js, который аннотирует циклические ссылки как строки, чтобы их можно было повторно подключить после синтаксического анализа. Де-циклически глубокое копирование безопасно пройти через формат JSON.преобразовать в строки. Наслаждайтесь!

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

цикл.js: Этот файл содержит две функции, JSON.децикл и формат JSON.ретроцикл, который позволяет кодировать циклические структуры и группы обеспечения доступности баз данных в 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));