我使用SignalR一个复杂的对象图回到我的JavaScript客户端。 这个对象图在整个对同一个对象多次引用,让SignalR / Json.NET返回JSON看起来很像这样的:
{
"$id": "57",
"Name": "_default",
"User": {
"$id": "58",
"UserTag": "ken",
"Sessions": [{
"$id": "59",
"SessionId": "0ca7474e-273c-4eb2-a0c1-1eba2f1a711c",
"User": {
"$ref": "58"
},
"Room": {
"$ref": "57"
}
}],
},
"Sessions": [{
"$ref": "59"
}]
}
(当然,有很多更复杂的现实生活中,但你的想法。)
当然,当Json.NET通过引用而不是通过值序列化,它给每个对象值(如$ ID "$id":"57"
,再后来只是指的是使用的ID对象(例如, "$ref":"57"
。到目前为止,我所知道的,当它是Json.NET(使用C#/。NET)是反序列化的引用,它把对象的适当情况下在适当的位置。
所有好为止-但什么是反序列化这些在JavaScript中的最佳方式,让我真正得到在适当的地方适当的对象实例,而不是只是奇怪$裁判领域的?
我大概可以写我自己的通用解串器,但我想象别人已经解决了这个问题,我倒宁愿不重新发明轮子的任何。 不幸的是,我的谷歌技能显然是不足以找到解决方案:-)。
编辑:
我看到有一个IETF建议草案对这种事情应该是怎样工作的。 它看起来像总是有帮助的道格拉斯Crockford的具有初步实现它。 不幸的是,IETF建议使用比Json.NET采用不同的模式。
嗯,我想这会做到这一点。 我修改Crockford的cycle.js来处理Json.NET使用参考格式。 而且由于打字稿是不是JavaScript无法形容更好的语言,我在TS重写了它。 我当然不发誓,它没有任何错误(如果有人指出出来,我会尝试修复“时间),但它似乎来处理复杂的对象图,我扔掉它为止。
export function retrocycle(obj: any): void {
var catalog: any[] = [];
catalogObject(obj, catalog);
resolveReferences(obj, catalog);
}
function catalogObject(obj, catalog: any[]):void {
// The catalogObject function walks recursively through an object graph
// looking for $id properties. When it finds an object with that property, then
// it adds it to the catalog under that key.
var i: number;
if (obj && typeof obj === 'object') {
var id:string = obj.$id;
if (typeof id === 'string') {
catalog[id] = obj;
}
if (Object.prototype.toString.apply(obj) === '[object Array]') {
for (i = 0; i < obj.length; i += 1) {
catalogObject(obj[i], catalog);
}
} else {
for (name in obj) {
if (typeof obj[name] === 'object') {
catalogObject(obj[name], catalog);
}
}
}
}
}
function resolveReferences(obj: any, catalog: any[]) {
// The resolveReferences function walks recursively through the object looking for $ref
// properties. When it finds one that has a value that is an id, then it
// replaces the $ref object with a reference to the object that is found in the catalog under
// that id.
var i:number, item:any, name:string, id:string;
if (obj && typeof obj === 'object') {
if (Object.prototype.toString.apply(obj) === '[object Array]') {
for (i = 0; i < obj.length; i += 1) {
item = obj[i];
if (item && typeof item === 'object') {
id = item.$ref;
if (typeof id === 'string') {
obj[i] = catalog[id];
} else {
resolveReferences(item, catalog);
}
}
}
} else {
for (name in obj) {
if (typeof obj[name] === 'object') {
item = obj[name];
if (item) {
id = item.$ref;
if (typeof id === 'string') {
obj[name] = catalog[id];
} else {
resolveReferences(item, catalog);
}
}
}
}
}
}
}
和等效JS:
function retrocycle(obj) {
var catalog = [];
catalogObject(obj, catalog);
resolveReferences(obj, catalog);
}
function catalogObject(obj, catalog) {
var i;
if (obj && typeof obj === 'object') {
var id = obj.$id;
if (typeof id === 'string') {
catalog[id] = obj;
}
if (Object.prototype.toString.apply(obj) === '[object Array]') {
for (i = 0; i < obj.length; i += 1) {
catalogObject(obj[i], catalog);
}
} else {
for (name in obj) {
if (typeof obj[name] === 'object') {
catalogObject(obj[name], catalog);
}
}
}
}
}
function resolveReferences(obj, catalog) {
var i, item, name, id;
if (obj && typeof obj === 'object') {
if (Object.prototype.toString.apply(obj) === '[object Array]') {
for (i = 0; i < obj.length; i += 1) {
item = obj[i];
if (item && typeof item === 'object') {
id = item.$ref;
if (typeof id === 'string') {
obj[i] = catalog[id];
} else {
resolveReferences(item, catalog);
}
}
}
} else {
for (name in obj) {
if (typeof obj[name] === 'object') {
item = obj[name];
if (item) {
id = item.$ref;
if (typeof id === 'string') {
obj[name] = catalog[id];
} else {
resolveReferences(item, catalog);
}
}
}
}
}
}
}
你还挺使用它像这样(假设你有SignalR集线器连接好):
$.connection.roomHub.server.joinRoom()
.done(function(room) {
retrocycle(room);
});
我也创建了一个快速和肮脏的小仓库出来到位桶吧: https://bitbucket.org/smithkl42/jsonnetdecycle 。
文章来源: Using JavaScript to deserialize references in a complex object graph from SignalR/Json.NET