如果我有来自json.net的序列化JSON,那么:
User:{id:1,{Foo{id:1,prop:1}},
FooList{$ref: "1",Foo{id:2,prop:13}}
我想让淘汰赛的输出超过FooList,但我不知道如何继续进行,因为$ ref的东西可能会抛出东西。
我认为解决方案是以某种方式通过不使用强制所有Foo在FooList中呈现:
PreserveReferencesHandling = PreserveReferencesHandling.Objects
但这似乎很浪费..
答案 0 :(得分:24)
我发现了一些错误并实现了数组支持:
function resolveReferences(json) {
if (typeof json === 'string')
json = JSON.parse(json);
var byid = {}, // all objects by id
refs = []; // references to objects that could not be resolved
json = (function recurse(obj, prop, parent) {
if (typeof obj !== 'object' || !obj) // a primitive value
return obj;
if (Object.prototype.toString.call(obj) === '[object Array]') {
for (var i = 0; i < obj.length; i++)
// check also if the array element is not a primitive value
if (typeof obj[i] !== 'object' || !obj[i]) // a primitive value
continue;
else if ("$ref" in obj[i])
obj[i] = recurse(obj[i], i, obj);
else
obj[i] = recurse(obj[i], prop, obj);
return obj;
}
if ("$ref" in obj) { // a reference
var ref = obj.$ref;
if (ref in byid)
return byid[ref];
// else we have to make it lazy:
refs.push([parent, prop, ref]);
return;
} else if ("$id" in obj) {
var id = obj.$id;
delete obj.$id;
if ("$values" in obj) // an array
obj = obj.$values.map(recurse);
else // a plain object
for (var prop in obj)
obj[prop] = recurse(obj[prop], prop, obj);
byid[id] = obj;
}
return obj;
})(json); // run it!
for (var i = 0; i < refs.length; i++) { // resolve previously unknown references
var ref = refs[i];
ref[0][ref[1]] = byid[ref[2]];
// Notice that this throws if you put in a reference at top-level
}
return json;
}
答案 1 :(得分:13)
您从服务器收到的json对象包含Circular References。在使用对象之前,您必须首先从对象中删除所有$ref
属性,意味着代替$ref : "1"
您必须放置此链接指向的对象。
在你的情况下,它可能是指向id为1的用户对象
为此你应该看看Douglas Crockfords Plugin on github。有一个cycle.js可以为你完成这项工作。
或者您可以使用以下代码(未经测试):
function resolveReferences(json) {
if (typeof json === 'string')
json = JSON.parse(json);
var byid = {}, // all objects by id
refs = []; // references to objects that could not be resolved
json = (function recurse(obj, prop, parent) {
if (typeof obj !== 'object' || !obj) // a primitive value
return obj;
if ("$ref" in obj) { // a reference
var ref = obj.$ref;
if (ref in byid)
return byid[ref];
// else we have to make it lazy:
refs.push([parent, prop, ref]);
return;
} else if ("$id" in obj) {
var id = obj.$id;
delete obj.$id;
if ("$values" in obj) // an array
obj = obj.$values.map(recurse);
else // a plain object
for (var prop in obj)
obj[prop] = recurse(obj[prop], prop, obj)
byid[id] = obj;
}
return obj;
})(json); // run it!
for (var i=0; i<refs.length; i++) { // resolve previously unknown references
var ref = refs[i];
ref[0][ref[1]] = byid[refs[2]];
// Notice that this throws if you put in a reference at top-level
}
return json;
}
让我知道它是否有帮助!
答案 2 :(得分:5)
如果您利用JSON.parse
的{{1}}参数,这实际上非常简单。
以下示例。请参阅浏览器控制台以获取输出,因为StackOverflow的代码段控制台输出无法准确显示结果。
reviver
答案 3 :(得分:3)
我在亚历山大·瓦西里耶夫的回答中遇到阵列修正问题。
我不能评论他的答案(没有足够的声誉点;-)),所以我不得不添加一个新答案...... (我有一个弹出窗口作为最佳做法,不回答其他答案,只关于原始问题 - bof)
if (Object.prototype.toString.call(obj) === '[object Array]') {
for (var i = 0; i < obj.length; i++) {
// check also if the array element is not a primitive value
if (typeof obj[i] !== 'object' || !obj[i]) // a primitive value
return obj[i];
if ("$ref" in obj[i])
obj[i] = recurse(obj[i], i, obj);
else
obj[i] = recurse(obj[i], prop, obj);
}
return obj;
}
答案 4 :(得分:2)
在接受的实现中,如果您正在检查数组并遇到原始值,您将返回该值并覆盖该数组。您希望继续检查数组的所有元素并在结尾返回数组。
function resolveReferences(json) {
if (typeof json === 'string')
json = JSON.parse(json);
var byid = {}, // all objects by id
refs = []; // references to objects that could not be resolved
json = (function recurse(obj, prop, parent) {
if (typeof obj !== 'object' || !obj) // a primitive value
return obj;
if (Object.prototype.toString.call(obj) === '[object Array]') {
for (var i = 0; i < obj.length; i++)
// check also if the array element is not a primitive value
if (typeof obj[i] !== 'object' || !obj[i]) // a primitive value
continue;
else if ("$ref" in obj[i])
obj[i] = recurse(obj[i], i, obj);
else
obj[i] = recurse(obj[i], prop, obj);
return obj;
}
if ("$ref" in obj) { // a reference
var ref = obj.$ref;
if (ref in byid)
return byid[ref];
// else we have to make it lazy:
refs.push([parent, prop, ref]);
return;
} else if ("$id" in obj) {
var id = obj.$id;
delete obj.$id;
if ("$values" in obj) // an array
obj = obj.$values.map(recurse);
else // a plain object
for (var prop in obj)
obj[prop] = recurse(obj[prop], prop, obj);
byid[id] = obj;
}
return obj;
})(json); // run it!
for (var i = 0; i < refs.length; i++) { // resolve previously unknown references
var ref = refs[i];
ref[0][ref[1]] = byid[ref[2]];
// Notice that this throws if you put in a reference at top-level
}
return json;
}
答案 5 :(得分:0)
我的解决方案(也适用于数组):
用法:rebuildJsonDotNetObj(jsonDotNetResponse)
代码:
_formkey