如何将表单的所有元素转换为JavaScript对象?

我希望有某种方法从表单自动构建JavaScript对象,而不必遍历每个元素。我不希望使用$('#formid').serialize();返回的字符串;,我也不希望$('#formid').serializeArray()返回映射;


当前回答

serializeArray已经做到了这一点。您只需将数据转换为所需格式:

function objectifyForm(formArray) {
    //serialize data function
    var returnArray = {};
    for (var i = 0; i < formArray.length; i++){
        returnArray[formArray[i]['name']] = formArray[i]['value'];
    }
    return returnArray;
}

注意与实际输入同名的隐藏字段,因为它们会被覆盖。

其他回答

我编写了一个jQuery模块jsForm,即使对于非常复杂的表单(也允许集合和其他更复杂的结构),它也可以实现这种双向。

它使用字段的名称(加上一些用于集合的特殊类)并匹配JSON对象。它允许自动复制用于收集和数据处理的DOM元素:

<html>
    <head>
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
        <script src="https://raw.github.com/corinis/jsForm/master/src/jquery.jsForm.js"></script>
        <script>
        $(function(){
            // Some JSON data
            var jsonData = {
                name: "TestName",   // Standard inputs
                description: "long Description\nMultiline", // Textarea
                links: [{href:'http://stackoverflow.com',description:'StackOverflow'}, {href:'http://www.github.com', description:'GitHub'}],   // Lists
                active: true,   // Checkbox
                state: "VISIBLE"    // Selects (enums)
            };

            // Initialize the form, prefix is optional and defaults to data
            $("#details").jsForm({
                data:jsonData
            });

            $("#show").click(function() {
                // Show the JSON data
                alert(JSON.stringify($("#details").jsForm("get"), null, " "));
            });
        });
        </script>
    </head>
    <body>
        <h1>Simpel Form Test</h1>
        <div id="details">
            Name: <input name="data.name"/><br/>
            <input type="checkbox" name="data.active"/> active<br/>
            <textarea name="data.description"></textarea><br/>
            <select name="data.state">
                <option value="VISIBLE">visible</option>
                <option value="IMPORTANT">important</option>
                <option value="HIDDEN">hidden</option>
            </select>
            <fieldset>
                <legend>Links</legend>
                <ul class="collection" data-field="data.links">
                    <li><span class="field">links.description</span> Link: <input name="links.href"/> <button class="delete">x</button></li>
                </ul>
            </fieldset>
            <button class="add" data-field="data.links">add a link</button><br/>
            Additional field: <input name="data.addedField"/>
        </div>
        <button id="show">Show Object</button>
    </body>
</html>

此函数返回转换为正确类型的所有值;

bool/string/(integer/floats)可能

虽然您需要jQuery来实现这一点,但由于serializeArray也是jQuery,所以没什么大不了的。

/**
 * serialized a form to a json object
 *
 * @usage: $("#myform").jsonSerialize();
 *
 */

(function($) {
    "use strict";
    $.fn.jsonSerialize = function() {
        var json = {};
        var array = $(this).serializeArray();
        $.each(array, function(key, obj) {
            var value = (obj.value == "") ? false : obj.value;
            if(value) {
                // check if we have a number
                var isNum = /^\d+$/.test(value);
                if(isNum) value = parseFloat(value);
                // check if we have a boolean
                var isBool = /^(false|true)+$/.test(value);
                if(isBool) value = (value!=="false");
            }
            json[obj.name] = value;
        });
        return json;
    }
})(jQuery);

一行(除了jQuery之外没有依赖项)使用传递给map方法的函数的固定对象绑定。

$('form').serializeArray().map(function(x){this[x.name] = x.value; return this;}.bind({}))[0]

它做什么?

"id=2&value=1&comment=ok" => Object { id: "2", value: "1", comment: "ok" }

适用于渐进式web应用程序(可以轻松支持常规表单提交操作和ajax请求)

我最近遇到了同样的问题,并推出了这个.toJSONjQuery插件,它将表单转换为具有相同结构的JSON对象。这对于动态生成的表单也特别有用,因为您希望用户在特定位置添加更多字段。

重点是你可能实际上想要构建一个表单,这样它本身就有一个结构,所以让我们假设你想要创建一个用户在城镇中插入他最喜欢的位置的表单:你可以想象这个表单代表一个<places></places>XML元素,包含用户喜欢的位置列表,因此是<place>列表</place>元素,每个元素包含例如<name></name>元素,一个<type></type>元素,然后是<activity>列表</activity>元素来表示您可以在这样的地方执行的活动。因此,您的XML结构如下所示:

<places>

    <place>

        <name>Home</name>
        <type>dwelling</type>

        <activity>sleep</activity>
        <activity>eat</activity>
        <activity>watch TV</activity>

    </place>

    <place>...</place>

    <place>...</place>

</places>

如果有一个JSON对象来表示这个精确的结构,那该有多酷,这样你就可以:

将此对象原样存储在任何类似CouchDB的数据库中从$_POST[]服务器端读取它,并检索一个正确的嵌套数组,然后可以对其进行语义操作使用一些服务器端脚本将其转换为格式良好的XML文件(即使您事先不知道其确切结构)在任何类似Node.js的服务器脚本中使用它

好的,现在我们需要考虑表单如何表示XML文件。

当然,<form>标记是根,但是我们有一个<place>元素,它是一个容器,而不是数据元素本身,所以我们不能为它使用输入标记。

这里是<fieldset>标记的用武之地!我们将使用<fieldset>标记来表示表单/XML表示中的所有容器元素,因此得到如下结果:

<form name="places">

    <fieldset name="place">

        <input type="text" name="name"/>
        <select name="type">
            <option value="dwelling">Dwelling</option>
            <option value="restoration">Restoration</option>
            <option value="sport">Sport</option>
            <option value="administrative">Administrative</option>
        </select>

        <input type="text" name="activity"/>
        <input type="text" name="activity"/>
        <input type="text" name="activity"/>

    </fieldset>

</form>

正如您在这个表单中看到的,我们打破了唯一名称的规则,但这是可以的,因为它们将被转换为一个元素数组,因此只能由数组中的索引引用。

此时,您可以看到表单中没有类似于name=“array[]”的名称,而且一切都很漂亮、简单、语义。

现在我们希望将此表单转换为JSON对象,该对象如下所示:

{'places':{

    'place':[

        {

            'name': 'Home',
            'type': 'dwelling',

            'activity':[

                 'sleep',
                 'eat',
                 'watch TV'

            ]

        },

        {...},

        {...}

    ]

}}

为了做到这一点,我在这里开发了一个jQuery插件,有人在这个CodeReview线程中帮助优化了这个插件,看起来像这样:

$.fn.toJSO = function () {
    var obj = {},
        $kids = $(this).children('[name]');
    if (!$kids.length) {
        return $(this).val();
    }
    $kids.each(function () {
        var $el = $(this),
            name = $el.attr('name');
        if ($el.siblings("[name=" + name + "]").length) {
            if (!/radio|checkbox/i.test($el.attr('type')) || $el.prop('checked')) {
                obj[name] = obj[name] || [];
                obj[name].push($el.toJSO());
            }
        } else {
            obj[name] = $el.toJSO();
        }
    });
    return obj;
};

我还写了一篇博文来解释这一点。

这会将表单中的所有内容转换为JSON(甚至是单选和复选框),您只需调用

$.post('script.php',('form').toJSO(), ...);

我知道有很多方法可以将表单转换为JSON对象,当然.serialize()和.serializeArray()在大多数情况下都非常有效,而且主要是为了使用,但我认为将表单编写为具有有意义名称的XML结构并将其转换为格式良好的JSON对象的整个想法值得一试,如果您需要检索动态生成的表单数据,那么可以添加同名输入标记而不必担心这一事实也非常有用。

我希望这对某人有所帮助!

所以我使用了公认的答案,发现了一个主要缺陷。它不支持以下输入数组:

<input type="checkbox" name="array[]" value="1"/>
<input type="checkbox" name="array[]" value="2"/>
<input type="checkbox" name="array[]" value="3"/>

这一小改动应该可以解决以下问题:

function objectifyForm(inp){
    var rObject = {};
    for (var i = 0; i < inp.length; i++){
        if(inp[i]['name'].substr(inp[i]['name'].length - 2) == "[]"){
            var tmp = inp[i]['name'].substr(0, inp[i]['name'].length-2);
            if(Array.isArray(rObject[tmp])){
                rObject[tmp].push(inp[i]['value']);
            } else{
                rObject[tmp] = [];
                rObject[tmp].push(inp[i]['value']);
            }
        } else{
            rObject[inp[i]['name']] = inp[i]['value'];
        }
    }
    return rObject;
}

记住将$(this).serializeArray()的输出传递给它;否则它不会起作用。