I'm using SignalR to return a complex object graph to my JavaScript client. This object graph has multiple references throughout to the same object, so the JSON that SignalR/Json.NET returns looks a lot like this:
{
"$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"
}]
}
(Of course, a lot more complicated in real life, but you get the idea.)
And of course, when Json.NET is serializing by reference rather than by value, it assigns each object a $id value (e.g., "$id":"57"
, and then later just refers to that object using that id (e.g., "$ref":"57"
. And so far as I can tell, when it is Json.NET (using C#/.NET) that is deserializing those references, it places the appropriate instances of the object in the appropriate places.
All good so far - but what's the best way to deserialize these in JavaScript, so that I actually get the appropriate object instances in the appropriate places, instead of just weird $ref fields?
I could presumably write my own general-purpose deserializer, but I have to imagine that somebody else has already tackled this problem, and I'd just as soon not reinvent any wheels. Unfortunately, my Google skills apparently aren't sufficient to locate that solution :-).
Edit:
I see that there's an IETF draft proposal about how this sort of thing is supposed to work. And it looks like the always helpful Douglas Crockford has a tentative implementation of it. Unfortunately, the IETF proposal uses a different schema than Json.NET uses.
Well, I think this will do it. I modified Crockford's cycle.js to handle the reference format that Json.NET uses. And because TypeScript is an unspeakably better language than JavaScript, I rewrote it in TS. I certainly don't swear that it has no bugs (if anybody points them out, I'll try to fix 'em), but it seems to handle the complex object graphs I've throw at it so far.
And the equivalent JS:
You use it kinda like so (assuming you've got SignalR hubs wired up):
I also created a quick-and-dirty little repository out on BitBucket for it: https://bitbucket.org/smithkl42/jsonnetdecycle.