我正在使用Newtonsoft JSON.Net来反序列化启用了PreserveReferencesHandling的对象。 jQuery不支持基于$ ref和$ id语法重新链接引用JSON.Net使用(我不知道jQuery是否支持任何容量的此功能)。
我尝试使用Douglas Crockford的cycle.js,但这似乎不适用于我的对象,返回的对象与传入的对象相同。
我对JSON.Net并不是很熟悉,但我似乎找不到任何可以序列化(或解析)其.NET组件输出的JSON的JavaScript库。
如何完成对象引用的重新组合?
答案 0 :(得分:4)
我也在寻找这个问题的解决方案,并最终破解了Douglas Crockford的JSON.retrocycle功能。他的函数不适用于$ ref = 某些数字,但它会查找类似xpath的内容。
这是我的快速和脏版本 - 不要按原样使用它 - 我没有进行任何清理,它可能应该是一个插件,但它完成了工作,并且足够好开始:
function retrocycle(o) {
var self = this;
self.identifiers = [];
self.refs = [];
self.rez = function (value) {
// The rez function walks recursively through the object looking for $ref
// properties. When it finds one that has a value that is a path, then it
// replaces the $ref object with a reference to the value that is found by
// the path.
var i, item, name, path;
if (value && typeof value === 'object') {
if (Object.prototype.toString.apply(value) === '[object Array]') {
for (i = 0; i < value.length; i += 1) {
item = value[i];
if (item && typeof item === 'object') {
path = item.$ref;
if (typeof path === 'string' && path != null) {
//self.refs[parseInt(path)] = {};
value[i] = self.identifiers[parseInt(path)]
} else {
self.identifiers[parseInt(item.$id)] = item;
self.rez(item);
}
}
}
} else {
for (name in value) {
if (typeof value[name] === 'object') {
item = value[name];
if (item) {
path = item.$ref;
if (typeof path === 'string' && path != null) {
//self.refs[parseInt(path)] = {};
value[name] = self.identifiers[parseInt(path)]
} else {
self.identifiers[parseInt(item.$id)] = item;
self.rez(item);
}
}
}
}
}
}
};
self.rez(o);
self.identifiers = [];
}
像这样使用:
$.post("url/function", { ID: params.ID }, function (data) {
retrocycle(data)
// data references should be fixed up now
}, "json");
答案 1 :(得分:0)
你必须在你的js解析器中进行双重查找。技术上保留引用处理是为了绕过循环引用,也就是说在解析过程中通常会导致堆栈溢出。
JSON没有处理此问题的本机语法。 Newtonsoft版本是一个自定义实现,因此解析JSON将是一个自定义实现。
如果您真的必须保留此类引用,那么XML可能是更好的解决方案。那里有一些json-> xml库。
这是一个可能有用的解析解决方案,或者至少是一个指南: https://blogs.oracle.com/sundararajan/entry/a_convention_for_circular_reference
答案 2 :(得分:0)
这是我的@Dimitri增强版。 @Dimitri代码有时无法重建引用。如果有人改进了代码,请告诉我。
此致 马可·阿尔维斯。
if (typeof JSON.retrocycle !== 'function') {
JSON.retrocycle = function retrocycle(o) {
//debugger;
var self = this;
self.identifiers = [];
self.refs = [];
self.buildIdentifiers = function (value) {
//debugger;
if (!value || typeof value !== 'object') {
return;
}
var item;
if (Object.prototype.toString.apply(value) === '[object Array]') {
for (var i = 0; i < value.length; i += 1) {
item = value[i];
if (!item || !item.$id || isNaN(item.$id)) {
if (item) {
self.buildIdentifiers(item);
}
continue;
}
self.identifiers[parseInt(item.$id)] = item;
self.buildIdentifiers(item);
}
return;
}
for (var name in value) {
if (typeof value[name] !== 'object') {
continue;
}
item = value[name];
if (!item || !item.$id || isNaN(item.$id)) {
if (item) {
self.buildIdentifiers(item);
}
continue;
}
self.identifiers[parseInt(item.$id)] = item;
self.buildIdentifiers(item);
}
};
self.rez = function (value) {
// The rez function walks recursively through the object looking for $ref
// properties. When it finds one that has a value that is a path, then it
// replaces the $ref object with a reference to the value that is found by
// the path.
var i, item, name, path;
if (value && typeof value === 'object') {
if (Object.prototype.toString.apply(value) === '[object Array]') {
for (i = 0; i < value.length; i += 1) {
item = value[i];
if (item && typeof item === 'object') {
if (item.$ref)
path = item.$ref;
if (typeof path === 'string' && path != null) {
//self.refs[parseInt(path)] = {};
value[i] = self.identifiers[parseInt(path)];
continue;
}
//self.identifiers[parseInt(item.$id)] = item;
self.rez(item);
}
}
} else {
for (name in value) {
if (typeof value[name] === 'object') {
item = value[name];
if (item) {
path = item.$ref;
if (typeof path === 'string' && path != null) {
//self.refs[parseInt(path)] = {};
value[name] = self.identifiers[parseInt(path)];
continue;
}
//self.identifiers[parseInt(item.$id)] = item;
self.rez(item);
}
}
}
}
}
};
self.buildIdentifiers(o);
self.rez(o);
self.identifiers = []; // Clears the array
};
}