我正在使用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提案草案,关于这种事情应该如何工作。看起来总是有用的道格拉斯·克罗克福德(Douglas
Crockford)尝试了它。不幸的是,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。
问题内容: 我正在尝试对a进行序列化/反序列化,如果对象是简单类型,这似乎很好,但是当对象更复杂时,它不起作用。 我有这个课: 在我的字典中,我添加了一个带有“重定向链”键的键和一些带有“状态”,“网址”,“父网址”键的简单字符串。我从JSON.Net返回的字符串如下所示: 我用来序列化的代码如下: 反序列化我正在做的事情: 字典恢复正常,所有字符串恢复正常,但是列表未正确反序列化。它只是作为 当
问题内容: 我的JSON有点弱,所以我需要一些帮助。 我正在尝试反序列化用户的JSON: 放入我用属性装饰的对象中: 我得到以下异常: Newtonsoft.Json.JsonSerializationException:在JSON中找不到必需的属性’user_id’。 这是因为JSON对象是一个数组吗?如果是这样,如何将其反序列化为一个User对象? 提前致谢! 问题答案: 正如Alexandr
问题内容: 我有一个带有JSON数组的有效JSON对象。JSON数组没有花括号,并且包含逗号分隔的混合类型列表。看起来像这样: 我创建了一个反映JSON结构的类,为复杂数组提供了一个List: 我也用列表列表进行了测试: 子模型如下所示: 在我的program.cs文件中,我正在反序列化如下: 当我运行该程序时,子对象(Rows)始终为。我究竟做错了什么? 问题答案: Json.Net没有将数组自
我正在做一个小组项目,我们遇到了一个软件序列化部分的问题。我们有类协议: 我们还有SearchResult类: 当我们通过客户端-服务器套接字连接编写协议类时,就会出现问题。问题是Protocol类中的TableModel对象在序列化/反序列化过程中的某个时刻变为null,而我们所做的任何事情都还没有解决这个问题。 到目前为止,我们已尝试: -在SearchResult中实现Serializabl
问题内容: 我正在尝试将一些JSON数据反序列化为应用程序的对象。到现在为止还不错,因为JSON数据上的属性是静态的(带有值的键)。现在,我得到了一个结果,其中的关键是动态数据。 这是一个示例JSON网址: http://en.wikipedia.org/w/api.php?action=query&format=json&pageids=6695&prop=info 由此产生的JSON是: 好的
问题内容: 我有一堂课 我想将下面的JSON数据反序列化到上面的类/对象中 我的想法是在JSON中是一个对象,但我只想获取(在JSON中)在反序列化期间将像在类中那样传递。 如何使用Json.NET实现该目标? 我相信我可以使用CustomJsonConverter完成它。但是我很困惑。docs中的示例仅用于,但不适用。 问题答案: 我只是使用上面在问题中提到的方法解决了我的问题。在我完整的代码下