Is there a javascript serializer for JSON.Net?

谁说我不能喝 提交于 2019-12-11 03:47:54

问题


I am using Newtonsoft JSON.Net to deserialize an object with PreserveReferencesHandling enabled. jQuery does not support relinking references based on the $ref and $id syntax JSON.Net uses (I don't know if jQuery supports this functionality in any capacity).

I tried using Douglas Crockford's cycle.js but that does not seem to work with my objects, the returned object is identical to the object which got passed in.

I am not incredibly familiar with JSON.Net, but I cannot seem to find any javascript libraries which would serialize (or parse) the JSON their .NET component outputs.

How can I accomplish putting back together object references?


回答1:


I was looking for a solution to this problem as well, and ended up hacking Douglas Crockford's JSON.retrocycle function. His function does not work for the $ref=some number, but it looks for something like an xpath.

This is my quick and dirty version - don't use this as is - I'm not doing any cleanup, and it probably should be a plugin, but it does the job and is good enough to get going:

function retrocycle(o) {
var self = this;
self.identifiers = [];
self.refs = [];

self.rez = function (value) {

    // The rez function walks recursively through the object looking for $ref
    // properties. When it finds one that has a value that is a path, then it
    // replaces the $ref object with a reference to the value that is found by
    // the path.

    var i, item, name, path;

    if (value && typeof value === 'object') {
        if (Object.prototype.toString.apply(value) === '[object Array]') {
            for (i = 0; i < value.length; i += 1) {
                item = value[i];
                if (item && typeof item === 'object') {
                    path = item.$ref;
                    if (typeof path === 'string' && path != null) {
                        //self.refs[parseInt(path)] = {};

                        value[i] = self.identifiers[parseInt(path)]
                    } else {
                        self.identifiers[parseInt(item.$id)] = item;
                        self.rez(item);
                    }
                }
            }
        } else {
            for (name in value) {
                if (typeof value[name] === 'object') {
                    item = value[name];
                    if (item) {
                        path = item.$ref;
                        if (typeof path === 'string' && path != null) {
                            //self.refs[parseInt(path)] = {};

                            value[name] = self.identifiers[parseInt(path)]
                        } else {
                            self.identifiers[parseInt(item.$id)] = item;
                            self.rez(item);
                        }
                    }
                }
            }
        }
    }

};
self.rez(o);
self.identifiers = [];
}

Use it like this:

    $.post("url/function", { ID: params.ID }, function (data) {

        retrocycle(data)

        // data references should be fixed up now

    }, "json");



回答2:


You would have to write in a double look-up into your js parser. Technically preserving reference handling is to get around circular references, which is to say what would normally cause a stack overflow during parsing.

JSON does not have a native syntax for handling this. Newtonsoft version is a custom implementation, thus parsing the JSON will be a custom implementation.

If you really have to preserve such references, XML may be a better solution. There are some json->xml libraries out there.

Here is one solution for parsing that may be of use, or at least a guide: https://blogs.oracle.com/sundararajan/entry/a_convention_for_circular_reference




回答3:


This is my enhanced version of @Dimitri. @Dimitri code sometimes isn't able to rebuild the references. If anyone improves the code, please, tell me.

Regards, Marco Alves.

if (typeof JSON.retrocycle !== 'function') {
    JSON.retrocycle = function retrocycle(o) {
        //debugger;

        var self = this;
        self.identifiers = [];
        self.refs = [];

        self.buildIdentifiers = function (value) {
            //debugger;

            if (!value || typeof value !== 'object') {
                return;
            }

            var item;

            if (Object.prototype.toString.apply(value) === '[object Array]') {
                for (var i = 0; i < value.length; i += 1) {
                    item = value[i];

                    if (!item || !item.$id || isNaN(item.$id)) {
                        if (item) {
                            self.buildIdentifiers(item);
                        }

                        continue;
                    }

                    self.identifiers[parseInt(item.$id)] = item;
                    self.buildIdentifiers(item);
                }

                return;
            }

            for (var name in value) {
                if (typeof value[name] !== 'object') {
                    continue;
                }

                item = value[name];

                if (!item || !item.$id || isNaN(item.$id)) {
                    if (item) {
                        self.buildIdentifiers(item);
                    }

                    continue;
                }

                self.identifiers[parseInt(item.$id)] = item;
                self.buildIdentifiers(item);
            }
        };

        self.rez = function (value) {

            // The rez function walks recursively through the object looking for $ref
            // properties. When it finds one that has a value that is a path, then it
            // replaces the $ref object with a reference to the value that is found by
            // the path.

            var i, item, name, path;

            if (value && typeof value === 'object') {
                if (Object.prototype.toString.apply(value) === '[object Array]') {
                    for (i = 0; i < value.length; i += 1) {
                        item = value[i];
                        if (item && typeof item === 'object') {

                            if (item.$ref)
                                path = item.$ref;

                            if (typeof path === 'string' && path != null) {
                                //self.refs[parseInt(path)] = {};

                                value[i] = self.identifiers[parseInt(path)];
                                continue;
                            }

                            //self.identifiers[parseInt(item.$id)] = item;
                            self.rez(item);
                        }
                    }
                } else {
                    for (name in value) {
                        if (typeof value[name] === 'object') {
                            item = value[name];
                            if (item) {
                                path = item.$ref;
                                if (typeof path === 'string' && path != null) {
                                    //self.refs[parseInt(path)] = {};

                                    value[name] = self.identifiers[parseInt(path)];
                                    continue;
                                }

                                //self.identifiers[parseInt(item.$id)] = item;
                                self.rez(item);
                            }
                        }
                    }
                }
            }

        };

        self.buildIdentifiers(o);
        self.rez(o);
        self.identifiers = []; // Clears the array
    };
}


来源:https://stackoverflow.com/questions/12865083/is-there-a-javascript-serializer-for-json-net

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!