gpt4 book ai didi

javascript - 使用 JavaScript 反序列化来自 SignalR/Json.NET 的复杂对象图中的引用

转载 作者:可可西里 更新时间:2023-11-01 01:51:26 24 4
gpt4 key购买 nike

我正在使用 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 中反序列化这些 的最佳方法是什么,以便我实际上在适当的位置获得适当的对象实例,而不仅仅是奇怪的 $ref 字段?

我大概可以编写我自己的通用反序列化器,但我必须想象其他人已经解决了这个问题,我不会重新发明任何轮子。不幸的是,我的 Google 技能显然不足以找到该解决方案:-)。

编辑:

我看到有一个 IETF draft proposal关于这种事情应该如何运作。看起来总是乐于助人的道格拉斯克罗克福德有一个 tentative implementation它的。遗憾的是,IETF 提案使用的架构与 Json.NET 使用的架构不同。

最佳答案

嗯,我想这就可以了。我修改了 Crockford 的 cycle.js处理 Json.NET 使用的引用格式。而且因为 TypeScript 是一种无法形容的比 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);
});

我还在 BitBucket 上为它创建了一个快速而简单的小存储库: https://bitbucket.org/smithkl42/jsonnetdecycle .

关于javascript - 使用 JavaScript 反序列化来自 SignalR/Json.NET 的复杂对象图中的引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13782052/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com