Преобразовать в строки на JavaScript вложенные объекты с петлей ссылки


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

function stringify(objectToCopy, exceptionClasses = []) {

    // Listify.
    var objects = [];

    var que = [objectToCopy];
    while(que.length > 0){
        var o = que.pop();
        objects.push(o);
        var propNames = Object.getOwnPropertyNames(o);
        for (let i = 0; i < propNames.length; i++) {
            const n = propNames[i];
            var property = o[n];
            if (
                typeof property == "object" && property != null &&
                objects.indexOf(property) == -1 &&
                que.indexOf(property) == -1 &&
                exceptionClasses.indexOf(property.constructor.name) == -1
            ) {
                que.push(property);
            }
        }
    }

    // Stringify.
    var stringifiedList = [];

    for (let i = 0; i < objects.length; i++) {
        const o = objects[i];

        var temp = {
            "className": o.constructor.name,
            "properties": [],
        };

        var propNames = Object.getOwnPropertyNames(o);
        for (let i = 0; i < propNames.length; i++) {
            const n = propNames[i];
            var property = o[n];
            if (typeof property == "object" && property != null){
                if (exceptionClasses.indexOf(property.constructor.name) == -1) {
                    temp.properties.push({
                        "isObject": true,
                        "name": n,
                        "content": objects.indexOf(property), // content will here refer to the index of where the object is.
                    });
                }
            }else{
                var content = JSON.stringify(property);
                if (content == null) {
                    content = null; // Converts from undefined to null.
                }
                temp.properties.push({
                    "isObject": false,
                    "name": n,
                    "content": content,
                });
            }
        }

        stringifiedList.push(temp);
    }

    //
    return JSON.stringify(stringifiedList);
}
function deStringify (string) {
    var stringifiedList = JSON.parse(string);


    // Listify.
    var objects = [];
    for (let i = 0; i < stringifiedList.length; i++) {
        const data = stringifiedList[i];

        var cleanName = /[a-zA-Z_$][0-9a-zA-Z_$]*/.exec(data.className).toString();

        if (cleanName != data.className) {
            throw "ERROR: Class name validation failed."
        }

        var newObject = Object.create(eval(cleanName).prototype);
        objects.push(newObject);
    }

    // Destringify
    for (let i = 0; i < stringifiedList.length; i++) {
        const data = stringifiedList[i];
        const obj = objects[i];

        for (let j = 0; j < data.properties.length; j++) {
            const property = data.properties[j];
            if (property.isObject){
                obj[property.name] = objects[property.content];
            }else{
                obj[property.name] = JSON.parse(property.content);
            }
        }
    }

    return objects[0];
}

// Testing.
var a = [6,5,4,3];
var b = [a, a, "alpha", "beta"];
b.push(b);
a.push(b);

var s = stringify(a);
console.log(deStringify(s));

/* Output:
(5) [6, 5, 4, 3, Array(5)]
    0:  6
    1:  5
    2:  4
    3:  3
    4:  Array(5)
        0:  (5) [6, 5, 4, 3, Array(5)]
        1:  (5) [6, 5, 4, 3, Array(5)]
        2:  "alpha"
        3:  "beta"
        4:  (5) [Array(5), Array(5), "alpha", "beta", Array(5)]
        length: 5
        __proto__:  Array(0)
    length: 5
    __proto__:  Array(0)
*/

Причина не только использовать JSON.stringify() из-за этого не сохранить прототипа, а также не поддерживает цикл ссылок. Такой подход Сокс? Есть ли что-то об объектах, я дублирую, что я скучаю, когда я только дублировать свои свойства? Я знаю, что этот код не работает для DOM-объектов или объектов, связанных с поддержкой WebGL.



Комментарии
1 ответ

JSON.stringify() и JSON.parse() были предназначены для сериализации и десериализации данных. Именно поэтому он пропускает без данных (функции, регулярные выражения и т. д.) на цели. Когда вы упоминаете сериализации прототипы, вы сериализации поведения и отношения объектов, а не данных. По той же причине, почему JSON является более предпочтительным по сравнению с XML для AJAX, потому что в JSON - это формат обмена данными, в то время как XML - документ в формате.

Я предлагаю вам переосмыслить ваш подход, прежде чем это станет кроличью нору.

Чистки рядов, JSON.serialize() принимает заменитель функцию в качестве второго аргумента, в то время как JSON.parse() принимает живительную функцию в качестве второго аргумента. Если вы строите какой-то объект сопоставителя, вы можете использовать заменитель для вставки метаданных о конструкторе для этого экземпляра, и использовать живительную подобрать, что метаданные и настройки, что экземпляр объекта создается.

1
ответ дан 28 марта 2018 в 12:03 Источник Поделиться