Сериализовать объект, который содержит значение циклического объекта
у меня есть объект (дерево разбора), который содержит дочерние узлы, которые являются ссылками на другие узлы.
Я хотел бы сериализовать этот объект, используя JSON.stringify()
, но я получаю : TypeError: cyclic object value
из-за конструкций, которые я упомянул.
Как я могу обойти это? Для меня не имеет значения, представлены ли эти ссылки на другие узлы или нет в сериализованном объекте.
С другой стороны, удаление этих свойств из объекта, когда они созданный кажется утомительным, и я бы не хотел вносить изменения в парсер (нарцисс).
5 ответов:
используйте второй параметр
stringify
на функции заменитель, чтобы исключить уже сериализованные объекты:var seen = []; JSON.stringify(obj, function(key, val) { if (val != null && typeof val == "object") { if (seen.indexOf(val) >= 0) { return; } seen.push(val); } return val; });
как правильно указано в других комментариях, этот код удаляет все "видимые" объекты, а не только "рекурсивные".
например:
a = {x:1}; obj = [a, a];
результат будет неверным. Если ваша структура такова, Крокфорд decycle - это более лучший вариант.
Я создал GitHub Gist, который способен обнаруживать циклические структуры, а также де-и кодирует их:https://gist.github.com/Hoff97/9842228
для преобразования просто используйте JSONE.stringify / JSONE.разбор. Он также де - и кодирует, функции. Если вы хотите отключить это просто удалите строки 32-48 и 61-85.
var strg = JSONE.stringify(cyclicObject); var cycObject = JSONE.parse(strg);
вы можете найти пример скрипки здесь:
большая заставка, и она показывает, где был.
<script> var jsonify=function(o){ var seen=[]; var jso=JSON.stringify(o, function(k,v){ if (typeof v =='object') { if ( !seen.indexOf(v) ) { return '__cycle__'; } seen.push(v); } return v; }); return jso; }; var obj={ g:{ d:[2,5], j:2 }, e:10 }; obj.someloopshere = [ obj.g, obj, { a: [ obj.e, obj ] } ]; console.log('jsonify=',jsonify(obj)); </script>
производит
jsonify = {"g":{"d":[2,5],"j":2},"e":10,"someloopshere":[{"d":[2,5],"j":2},"__cycle__",{"a":[10,"__cycle__"]}]}
function stringifyObject ( obj ) { if ( _.isArray( obj ) || !_.isObject( obj ) ) { return obj.toString() } var seen = []; return JSON.stringify( obj, function( key, val ) { if (val != null && typeof val == "object") { if ( seen.indexOf( val ) >= 0 ) return seen.push( val ) } return val } ); }
предварительное условие отсутствовало, в противном случае целочисленные значения в объектах массива усекаются, т. е. [[ 08.11.2014 12:30:13, 1095 ]] 1095 уменьшается до 095.
Я также создаю проект github, который может сериализовать циклический объект и восстановить класс, если вы сохраните его в атрибуте serializename как строку
var d={} var a = {b:25,c:6,enfant:d}; d.papa=a; var b = serializeObjet(a); assert.equal( b, "{0:{b:25,c:6,enfant:'tab[1]'},1:{papa:'tab[0]'}}" ); var retCaseDep = parseChaine(b) assert.equal( retCaseDep.b, 25 ); assert.equal( retCaseDep.enfant.papa, retCaseDep );
https://github.com/bormat/serializeStringifyParseCyclicObject
изменить: Я трансформирую свой скрипт для NPM https://github.com/bormat/borto_circular_serialize и у меня есть изменить имена функций с французского на английский.