[英]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.