如何在JSON.stringify中找到循环结构:Uncaught TypeError:将循环结构转换为JSON?

时间:2021-10-05 19:43:42

When I get Uncaught TypeError: Converting circular structure to JSON on a large structure it can be very difficult to find out where exactly the circular reference is.

当我得到Uncaught TypeError:在大型结构上将循环结构转换为JSON时,很难找到圆形引用的确切位置。

Is there a simple way to find/debug the circular element in the data structure?

有没有一种简单的方法来查找/调试数据结构中的循环元素?

1 个解决方案

#1


4  

I haven't found a simple method to do it, other people seem to be suggesting using custom replacer function in JSON.stringify to control which properties have been visited.

我还没有找到一个简单的方法,其他人似乎建议在JSON.stringify中使用自定义替换函数来控制访问过哪些属性。

I've attempted to write such replacer:

我试图写这样的替换者:

function detector(obj) {
    function collector (stack, key, val) {
        var idx = stack[stack.length - 1].indexOf(key);

        try {
            var props = Object.keys(val);
            if (!props.length) throw props;
            props.unshift({idx : idx});
            stack.push(props);
        } catch (e) {
            while (!(stack[stack.length - 1].length - 2)) {
                idx = stack[stack.length -1][0].idx;
                stack.pop();
            }

            if (idx + 1) {
                stack[stack.length - 1].splice(idx, 1);
            }
        }

        return val;
    }

    var stack = [[]];

    try {
        JSON.stringify(obj, collector.bind(null, stack));
    } catch (e) {
        if (e.message.indexOf('circular') !== -1) {
            var idx = 0;
            var path = '';
            var parentProp = '';
            while(idx + 1) {
                idx = stack.pop()[0].idx;
                parentProp = stack[stack.length - 1][idx];
                if (!parentProp) break;
                path = '.' + parentProp + path;
            }

            console.log(path);
        }
    }
}

What it does is while traversing the JSON tree (probably tree :)) it collects names of properties which have been visited and as soon as JSON.stringify detects circular reference and throws, 'stack' variable will contain a trace of which subtree it was traversing. And it logs this path to console.

它的作用是遍历JSON树(可能是树:))它收集已访问过的属性的名称,一旦JSON.stringify检测到循环引用和抛出,'stack'变量将包含它的哪个子树的跟踪遍历。它将此路径记录到控制台。

However, this is not a heavily tested solution.

但是,这不是经过严格测试的解决方案。

#1


4  

I haven't found a simple method to do it, other people seem to be suggesting using custom replacer function in JSON.stringify to control which properties have been visited.

我还没有找到一个简单的方法,其他人似乎建议在JSON.stringify中使用自定义替换函数来控制访问过哪些属性。

I've attempted to write such replacer:

我试图写这样的替换者:

function detector(obj) {
    function collector (stack, key, val) {
        var idx = stack[stack.length - 1].indexOf(key);

        try {
            var props = Object.keys(val);
            if (!props.length) throw props;
            props.unshift({idx : idx});
            stack.push(props);
        } catch (e) {
            while (!(stack[stack.length - 1].length - 2)) {
                idx = stack[stack.length -1][0].idx;
                stack.pop();
            }

            if (idx + 1) {
                stack[stack.length - 1].splice(idx, 1);
            }
        }

        return val;
    }

    var stack = [[]];

    try {
        JSON.stringify(obj, collector.bind(null, stack));
    } catch (e) {
        if (e.message.indexOf('circular') !== -1) {
            var idx = 0;
            var path = '';
            var parentProp = '';
            while(idx + 1) {
                idx = stack.pop()[0].idx;
                parentProp = stack[stack.length - 1][idx];
                if (!parentProp) break;
                path = '.' + parentProp + path;
            }

            console.log(path);
        }
    }
}

What it does is while traversing the JSON tree (probably tree :)) it collects names of properties which have been visited and as soon as JSON.stringify detects circular reference and throws, 'stack' variable will contain a trace of which subtree it was traversing. And it logs this path to console.

它的作用是遍历JSON树(可能是树:))它收集已访问过的属性的名称,一旦JSON.stringify检测到循环引用和抛出,'stack'变量将包含它的哪个子树的跟踪遍历。它将此路径记录到控制台。

However, this is not a heavily tested solution.

但是,这不是经过严格测试的解决方案。