Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何从Json.NET序列化的Json恢复循环引用(例如“$id”)?_Javascript_Json_Serialization_Circular Reference - Fatal编程技术网

Javascript 如何从Json.NET序列化的Json恢复循环引用(例如“$id”)?

Javascript 如何从Json.NET序列化的Json恢复循环引用(例如“$id”)?,javascript,json,serialization,circular-reference,Javascript,Json,Serialization,Circular Reference,是否有一个现有的javascript库可以使用引用循环处理反序列化Json.Net { "$id": "1", "AppViewColumns": [ { "$id": "2", "AppView": {"$ref":"1"}, "ColumnID": 1, } ] } 这应该反序列化到一个对象,该对象在数组中的对象和外部对象之间有一个引用循环,但是可以使用标准的JS

是否有一个现有的javascript库可以使用引用循环处理反序列化Json.Net

{
    "$id": "1",
    "AppViewColumns": [
        {
            "$id": "2",
            "AppView": {"$ref":"1"},
            "ColumnID": 1,
        }
    ]
}

这应该反序列化到一个对象,该对象在数组中的对象和外部对象之间有一个引用循环,但是可以使用标准的
JSON.parse
方法,然后手动遍历恢复循环引用的结果——这只是一个基于$id属性的简单存储/查找。(类似的方法可用于逆转过程。)

下面是一些使用这种方法的示例代码。这段代码假设JSON已经被解析为相关的JS对象图——它还修改了提供的数据。YMMV

function restoreJsonNetCR(g) {
  var ids = {};

  function relink (s) {
    // we care naught about primitives
    if (s === null || typeof s !== "object") { return s; }

    var id = s['$id'];
    delete s['$id'];

    // either return previously known object, or
    // remember this object linking for later
    if (ids[id]) {
      return ids[id];
    }
    ids[id] = s;

    // then, recursively for each key/index, relink the sub-graph
    if (s.hasOwnProperty('length')) {
      // array or array-like; a different guard may be more appropriate
      for (var i = 0; i < s.length; i++) {
        s[i] = relink(s[i]);
      }
    } else {
      // other objects
      for (var p in s) {
        if (s.hasOwnProperty(p)) {
          s[p] = relink(s[p]);
        }
      }
    }

    return s;
  }

  return relink(g);
}


DrSammyD创建了一个下划线插件变体。

好的,所以我创建了一个更健壮的方法,它将使用$id和$ref,因为json.net实际上就是这样处理循环引用的。此外,您必须在注册id后获取引用,否则它将找不到被引用的对象,因此我还必须保留请求引用的对象,以及它们要设置的属性和它们请求的id

这在很大程度上是基于lodash/下划线的

(function (factory) {
    'use strict';
    if (typeof define === 'function' && define.amd) {
        define(['lodash'], factory);
    } else {
        factory(_);
    }
})(function (_) {
    var opts = {
        refProp: '$ref',
        idProp: '$id',
        clone: true
    };
    _.mixin({
        relink: function (obj, optsParam) {
            var options = optsParam !== undefined ? optsParam : {};
            _.defaults(options, _.relink.prototype.opts);
            obj = options.clone ? _.clone(obj, true) : obj;
            var ids = {};
            var refs = [];
            function rl(s) {
                // we care naught about primitives
                if (!_.isObject(s)) {
                    return s;
                }
                if (s[options.refProp]) {
                    return null;
                }
                if (s[options.idProp] === 0 || s[options.idProp]) {
                    ids[s[options.idProp]] = s;
                }
                delete s[options.idProp];
                _(s).pairs().each(function (pair) {
                    if (pair[1]) {
                        s[pair[0]] = rl(pair[1]);
                        if (s[pair[0]] === null) {
                            if (pair[1][options.refProp] !== undefined) {
                                refs.push({ 'parent': s, 'prop': pair[0], 'ref': pair[1][options.refProp] });
                            }
                        }
                    }
                });

                return s;
            }

            var partialLink = rl(obj);
            _(refs).each(function (recordedRef) {
                recordedRef['parent'][recordedRef['prop']] = ids[recordedRef['ref']] || {};
            });
            return partialLink;
        },
        resolve: function (obj, optsParam) {
            var options = optsParam !== undefined ? optsParam : {};
            _.defaults(options, _.resolve.prototype.opts);
            obj = options.clone ? _.clone(obj, true) : obj;
            var objs = [{}];

            function rs(s) {
                // we care naught about primitives
                if (!_.isObject(s)) {
                    return s;
                }
                var replacementObj = {};

                if (objs.indexOf(s) != -1) {
                    replacementObj[options.refProp] = objs.indexOf(s);
                    return replacementObj;
                }
                objs.push(s);
                s[options.idProp] = objs.indexOf(s);
                _(s).pairs().each(function (pair) {
                    s[pair[0]] = rs(pair[1]);
                });

                return s;
            }

            return rs(obj);
        }
    });
    _(_.resolve.prototype).assign({ opts: opts });
    _(_.relink.prototype).assign({ opts: opts });
});

我创建了一个

,给出的答案几乎对我有用,但最新版本的MVC、JSON.Net和DNX使用了“$ref”和“$id”,它们可能不符合顺序。所以我修改了user2864740的答案

我应该注意,这段代码不处理数组引用,这也是可能的

函数RestoreJsonNetReferences(g){
变量id={};
函数getID(s){
//我们根本不关心原语
如果(s===null | | typeof s!==“object”){返回s;}
var id=s['$id'];
如果(id的类型!=“未定义”){
删除s['$id'];
//返回以前已知的对象,或
//请记住此对象链接供以后使用
if(id[id]){
抛出“找到重复ID”+ID+”;
}
id[id]=s;
}
//然后,递归地为每个键/索引重新链接子图
如果(s.hasOwnProperty('length')){
//阵列或类似阵列;不同的防护可能更合适
对于(变量i=0;i}
是的,在浏览器中,我还希望它以相同的方式再次序列化。这是我正在使用的要点的最终版本相关或重复:。我想我们还需要一个重新序列化程序。。。我可能会让它成为lodash的插件/underscore@DrSammyD如果你想从另一个方向回去,那么是的。但是-也许您不需要这两个方向的额外数据?我刚刚创建了一个双向的JSFIDLE。你愿意把它包括在你的答案里吗@DrSammyD可以随意编辑答案(或添加您自己的答案)。我加入了fiddle链接,以便更方便地使用。对于dnx中最新版本的JSON.Net,这对我来说不起作用。它同时使用“$id”和“$ref”,它们可能出现故障。我已经修改了你的答案。数组引用是指
“$values”
?我遇到了这个问题,通过检查
p==“$values”
,然后用重新链接替换
s
,而不是更新
s[p]
(即
s[“$values”]
)似乎可以解决这个问题。。如果这有道理的话。
(function (factory) {
    'use strict';
    if (typeof define === 'function' && define.amd) {
        define(['lodash'], factory);
    } else {
        factory(_);
    }
})(function (_) {
    var opts = {
        refProp: '$ref',
        idProp: '$id',
        clone: true
    };
    _.mixin({
        relink: function (obj, optsParam) {
            var options = optsParam !== undefined ? optsParam : {};
            _.defaults(options, _.relink.prototype.opts);
            obj = options.clone ? _.clone(obj, true) : obj;
            var ids = {};
            var refs = [];
            function rl(s) {
                // we care naught about primitives
                if (!_.isObject(s)) {
                    return s;
                }
                if (s[options.refProp]) {
                    return null;
                }
                if (s[options.idProp] === 0 || s[options.idProp]) {
                    ids[s[options.idProp]] = s;
                }
                delete s[options.idProp];
                _(s).pairs().each(function (pair) {
                    if (pair[1]) {
                        s[pair[0]] = rl(pair[1]);
                        if (s[pair[0]] === null) {
                            if (pair[1][options.refProp] !== undefined) {
                                refs.push({ 'parent': s, 'prop': pair[0], 'ref': pair[1][options.refProp] });
                            }
                        }
                    }
                });

                return s;
            }

            var partialLink = rl(obj);
            _(refs).each(function (recordedRef) {
                recordedRef['parent'][recordedRef['prop']] = ids[recordedRef['ref']] || {};
            });
            return partialLink;
        },
        resolve: function (obj, optsParam) {
            var options = optsParam !== undefined ? optsParam : {};
            _.defaults(options, _.resolve.prototype.opts);
            obj = options.clone ? _.clone(obj, true) : obj;
            var objs = [{}];

            function rs(s) {
                // we care naught about primitives
                if (!_.isObject(s)) {
                    return s;
                }
                var replacementObj = {};

                if (objs.indexOf(s) != -1) {
                    replacementObj[options.refProp] = objs.indexOf(s);
                    return replacementObj;
                }
                objs.push(s);
                s[options.idProp] = objs.indexOf(s);
                _(s).pairs().each(function (pair) {
                    s[pair[0]] = rs(pair[1]);
                });

                return s;
            }

            return rs(obj);
        }
    });
    _(_.resolve.prototype).assign({ opts: opts });
    _(_.relink.prototype).assign({ opts: opts });
});