将JSON对象转换为嵌套表单字段?

时间:2021-03-09 15:56:48

Anyone know of a good way to convert a JSON object to nested form fields.

任何人都知道将JSON对象转换为嵌套表单字段的好方法。

For example: consider a JSON object:

例如:考虑一个JSON对象:

{'a':{'b':{'c':'1200'}}}, 'z':'foo', 'bar':{'baz':'1', 'id':2}}

I should get:

我应该得到:

{'a[b][c]':'1200', 'z':'foo', 'bar[baz]':'1', 'bar[id]':2};

Any ideas?

I am currently using jquery and it feels like something like this already exists, if not I can simply roll my own with a crazy algorithm, but I'd rather use something with a proven track record.

我目前正在使用jquery,感觉像这样的东西已经存在,如果不是我可以用一个疯狂的算法简单地推出自己的东西,但我宁愿使用具有可靠记录的东西。

3 个解决方案

#1


So, I have no clue why you want to do what you say you want to do, and I hope you will fill us all in, but this code should be close enough for you to be able to tweak it (this is based on some code of mine that I use to find differences in JavaScript object graphs):

所以,我不知道你为什么要做你想做的事情,我希望你能填补我们的全部,但是这段代码应该足够接近你能够调整它(这是基于一些我用来查找JavaScript对象图中的差异的我的代码):

function doStrangeThing(obj) {
   var propertyChanges = [];
    var objectGraphPath = [];
    (function(obj, refObj) {
        if ( obj.constructor == Object || (obj.constructor != Number &&
             obj.constructor != String && obj.constructor != Date && obj.constructor != Boolean &&
             obj.constructor != RegExp && obj.constructor != Function)) {
            for (var property in obj) {
                objectGraphPath.push((objectGraphPath.length > 0) ? "[" + property + "]" : property);
                if (obj[property].constructor != Function) {
                    if (!refObj[property]) refObj[property] = {};
                    arguments.callee(obj[property], refObj[property]);
                }
                objectGraphPath.pop();
            }
        } else if (obj.constructor != Function) {
            if (obj != refObj) {
                propertyChanges.push("\"" + objectGraphPath.join("") + "\":\"" + obj.toString() + "\"");
            }
        }
    })(obj, {});
    return "{" + propertyChanges.join(",") + "}";
}

Here is what I did to test it:

以下是我测试它的方法:

doStrangeThing({'a':{'b':{'c':'1200'}}, 'z':'foo', 'bar':{'baz':'1', 'id':2}});

Which results in this value:

这导致了这个值:

{"a[b][c]":"1200","z":"foo","bar[baz]":"1","bar[id]":"2"}

Hope that is useful to you in some way...

希望以某种方式对你有用......

#2


obj = {'a':{'b':{'c':'1200'}}}, 'z':'foo', 'bar':{'baz':'1', 'id':2}}

is internally equivalent to

在内部相当于

{['a']['b']['c']:'1200', ['z']:'foo', ['bar']['baz']:'1', ['bar']['id']:2}

Please note that this is not JSON object anymore.

请注意,这不再是JSON对象。

You already can refer first object properties in this way:

您已经可以通过以下方式引用第一个对象属性:

var z = obj['a']['b']['c']   // 1200

Is it enough for your needs? Do you really want to convert property names to variables?

这足以满足您的需求吗?你真的想将属性名称转换为变量吗?

#3


I would actually recommend a function that takes a nested JSON object and turns it into a HTTP POST string. jQuery will accept that for all of its arguments that require HTTP parameters.

我实际上会推荐一个带有嵌套JSON对象并将其转换为HTTP POST字符串的函数。 jQuery将接受所有需要HTTP参数的参数。

I have written and used the function below in several production apps (use at your own risk):

我在几个生产应用程序中编写并使用了以下功能(使用风险自负):

$.httpSerialize = function(items, parentName) {
    var serializedItems = [], serialize = arguments.callee, encodeItem =     function(key, value) {
        if (value === null || typeof value == 'undefined') return value;
        if (value.constructor == Array) {return serialize(value, key);}
        return (value.constructor == Object)
            ? serialize(value, key)
            : (value === true || value === false)
                ? key+"="+new Number(value)
                : key+"="+encodeURIComponent(value);
    };

    if (items.constructor == Array) {
        parentName = parentName || 'item';
        for (var i = 0; i < items.length; i++) {
            var key = parentName+'['+i+']', value = items[i];
            serializedItems.push(encodeItem(key, value));
        }
    } else {
        parentName = parentName || '';
        for (var key in items) {
            var value = items[key];
            if (parentName) {
                serializedItems.push(encodeItem(parentName+'['+encodeURIComponent(key)+']', value));
            } else {
                serializedItems.push(encodeItem(encodeURIComponent(key), value));
            }
        }
    }
    return serializedItems.join("&");
};

#1


So, I have no clue why you want to do what you say you want to do, and I hope you will fill us all in, but this code should be close enough for you to be able to tweak it (this is based on some code of mine that I use to find differences in JavaScript object graphs):

所以,我不知道你为什么要做你想做的事情,我希望你能填补我们的全部,但是这段代码应该足够接近你能够调整它(这是基于一些我用来查找JavaScript对象图中的差异的我的代码):

function doStrangeThing(obj) {
   var propertyChanges = [];
    var objectGraphPath = [];
    (function(obj, refObj) {
        if ( obj.constructor == Object || (obj.constructor != Number &&
             obj.constructor != String && obj.constructor != Date && obj.constructor != Boolean &&
             obj.constructor != RegExp && obj.constructor != Function)) {
            for (var property in obj) {
                objectGraphPath.push((objectGraphPath.length > 0) ? "[" + property + "]" : property);
                if (obj[property].constructor != Function) {
                    if (!refObj[property]) refObj[property] = {};
                    arguments.callee(obj[property], refObj[property]);
                }
                objectGraphPath.pop();
            }
        } else if (obj.constructor != Function) {
            if (obj != refObj) {
                propertyChanges.push("\"" + objectGraphPath.join("") + "\":\"" + obj.toString() + "\"");
            }
        }
    })(obj, {});
    return "{" + propertyChanges.join(",") + "}";
}

Here is what I did to test it:

以下是我测试它的方法:

doStrangeThing({'a':{'b':{'c':'1200'}}, 'z':'foo', 'bar':{'baz':'1', 'id':2}});

Which results in this value:

这导致了这个值:

{"a[b][c]":"1200","z":"foo","bar[baz]":"1","bar[id]":"2"}

Hope that is useful to you in some way...

希望以某种方式对你有用......

#2


obj = {'a':{'b':{'c':'1200'}}}, 'z':'foo', 'bar':{'baz':'1', 'id':2}}

is internally equivalent to

在内部相当于

{['a']['b']['c']:'1200', ['z']:'foo', ['bar']['baz']:'1', ['bar']['id']:2}

Please note that this is not JSON object anymore.

请注意,这不再是JSON对象。

You already can refer first object properties in this way:

您已经可以通过以下方式引用第一个对象属性:

var z = obj['a']['b']['c']   // 1200

Is it enough for your needs? Do you really want to convert property names to variables?

这足以满足您的需求吗?你真的想将属性名称转换为变量吗?

#3


I would actually recommend a function that takes a nested JSON object and turns it into a HTTP POST string. jQuery will accept that for all of its arguments that require HTTP parameters.

我实际上会推荐一个带有嵌套JSON对象并将其转换为HTTP POST字符串的函数。 jQuery将接受所有需要HTTP参数的参数。

I have written and used the function below in several production apps (use at your own risk):

我在几个生产应用程序中编写并使用了以下功能(使用风险自负):

$.httpSerialize = function(items, parentName) {
    var serializedItems = [], serialize = arguments.callee, encodeItem =     function(key, value) {
        if (value === null || typeof value == 'undefined') return value;
        if (value.constructor == Array) {return serialize(value, key);}
        return (value.constructor == Object)
            ? serialize(value, key)
            : (value === true || value === false)
                ? key+"="+new Number(value)
                : key+"="+encodeURIComponent(value);
    };

    if (items.constructor == Array) {
        parentName = parentName || 'item';
        for (var i = 0; i < items.length; i++) {
            var key = parentName+'['+i+']', value = items[i];
            serializedItems.push(encodeItem(key, value));
        }
    } else {
        parentName = parentName || '';
        for (var key in items) {
            var value = items[key];
            if (parentName) {
                serializedItems.push(encodeItem(parentName+'['+encodeURIComponent(key)+']', value));
            } else {
                serializedItems.push(encodeItem(encodeURIComponent(key), value));
            }
        }
    }
    return serializedItems.join("&");
};