簡體   English   中英

如何從Json.NET序列化的JSON恢復循環引用(例如“ $ id”)?

[英]How to restore circular references (e.g. “$id”) from Json.NET-serialized JSON?

是否存在現有的JavaScript庫,該庫將通過引用循環處理反序列化Json.Net?

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

這應該反序列化為一個對象,該對象在數組中的對象和外部對象之間具有引用循環

給出的答案幾乎對我有用,但是最新版本的MVC,JSON.Net和DNX使用“ $ ref”和“ $ id”,它們可能會出現故障。 所以我修改了user2864740的答案。

我應該注意,此代碼處理數組引用,這也是可能的。

 function RestoreJsonNetReferences(g) { var ids = {}; function getIds(s) { // we care naught about primitives if (s === null || typeof s !== "object") { return s; } var id = s['$id']; if (typeof id != "undefined") { delete s['$id']; // either return previously known object, or // remember this object linking for later if (ids[id]) { throw "Duplicate ID " + id + "found."; } 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++) { getIds(s[i]); } } else { // other objects for (var p in s) { if (s.hasOwnProperty(p)) { getIds(s[p]); } } } } function relink(s) { // we care naught about primitives if (s === null || typeof s !== "object") { return s; } var id = s['$ref']; delete s['$ref']; // either return previously known object, or // remember this object linking for later if (typeof id != "undefined") { return ids[id]; } // 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; } getIds(g); return relink(g); } 

好的,所以我創建了一個更健壯的方法,該方法將同時使用$ 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 });
});

我在這里創建了要點

我不知道有這樣的支持的現有庫,但是可以使用標准的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);
}

和用法

var d = {
    "$id": "1",
    "AppViewColumns": [
        {
            "$id": "2",
            "AppView": {"$id":"1"},
            "ColumnID": 1,
        }
    ]
};

d = restoreJsonNetCR(d);
// the following works well in Chrome, YMMV in other developer tools
console.log(d);

DrSammyD創建了具有往返支持的下划線插件變體。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM