Skip to content Skip to sidebar Skip to footer

Using Javascript To Deserialize References In A Complex Object Graph From Signalr/json.net

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.N

Solution 1:

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.

exportfunctionretrocycle(obj: any): void {
    varcatalog: any[] = [];
    catalogObject(obj, catalog);
    resolveReferences(obj, catalog);
}

functioncatalogObject(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.vari: number;
    if (obj && typeof obj === 'object') {
        varid: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);
                }
            }
        }
    }
}

functionresolveReferences(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.vari: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);
                        }
                    }
                }
            }
        }
    }
}

And the equivalent JS:

functionretrocycle(obj) {
    var catalog = [];
    catalogObject(obj, catalog);
    resolveReferences(obj, catalog);
}

functioncatalogObject(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);
                }
            }
        }
    }
}

functionresolveReferences(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);
                        }
                    }
                }
            }
        }
    }
}

You use it kinda like so (assuming you've got SignalR hubs wired up):

$.connection.roomHub.server.joinRoom()
    .done(function(room) {
        retrocycle(room);
    });

I also created a quick-and-dirty little repository out on BitBucket for it: https://bitbucket.org/smithkl42/jsonnetdecycle.

Post a Comment for "Using Javascript To Deserialize References In A Complex Object Graph From Signalr/json.net"