代码之家  ›  专栏  ›  技术社区  ›  Tawani

将html表单字段转换为具有内部对象的json对象

  •  5
  • Tawani  · 技术社区  · 15 年前

    给定以下HTML表单:

    <form id="myform">
      Company: <input type="text" name="Company" value="ACME, INC."/>
      First Name: <input type="text" name="Contact.FirstName" value="Daffy"/>
      Last Name: <input type="text" name="Contact.LastName" value="Duck"/>
    </form>
    

    用javascript将此表单序列化为json对象的最佳方式是:

    {
      Company:"ACME, INC.",
      Contact:{FirstName:"Daffy", LastName:"Duck"}
    }
    

    还要注意,字段名中可能有多个“.”符号。

    5 回复  |  直到 15 年前
        1
  •  12
  •   Pointy    15 年前

    我认为您应该这样做:对于每个输入,首先在分隔符处拆分名称(字符“.”)。现在,你有一系列的名字。然后可以遍历该数组,确保每次遇到新的名称段时,目标“assembly”对象(和子对象)都有容器。当数组中有1个元素时,只需添加该值。

    $.fn.extractObject = function() {
      var accum = {};
      function add(accum, namev, value) {
        if (namev.length == 1)
          accum[namev[0]] = value;
        else {
          if (accum[namev[0]] == null)
            accum[namev[0]] = {};
          add(accum[namev[0]], namev.slice(1), value);
        }
      }; 
      this.find('input, textarea, select').each(function() {
        add(accum, $(this).attr('name').split('.'), $(this).val());
      });
      return accum;
    });
    // ...
    
    var object = $('#myform').extractObject();
    

    我只是编造了一些,所以可能有一两个bug;我不记得所有的浏览器是否都有“slice”,但我认为它们都有。

    (编辑:我忘记了 split() )

        2
  •  2
  •   T.J. Crowder    15 年前

    您可以按名称在表单字段中循环,使用 String#split 在点上拆分名称,并构建结果结构。概念代码:

    function serializeDeep(form) {
        var rv, obj, elements, element, index, names, nameIndex, value;
    
        rv = {};
        elements = form.elements;
        for (index = 0; index < elements.length; ++index) {
            element = elements[index];
            name = element.name;
            if (name) {
                value = $(element).val();
                names = name.split(".");
                obj = rv;
                for (nameIndex = 0; nameIndex < names.length; ++nameIndex) {
                    name = names[nameIndex];
                    if (nameIndex == names.length - 1) {
                        obj[name] = value;
                    }
                    else {
                        obj = obj[name] = obj[name] || {};
                    }
                }
            }
        }
        return rv;
    }
    

    请注意,这不允许字段具有重复的名称(应该创建数组),也不能优雅地处理使用名称“foo”和“foo.bar”的情况。但它应该让你开始。

        3
  •  1
  •   errordeveloper    13 年前

    我是这样处理的:

    $('#Myform').attr('onsubmit', 'test()');
    
    function test() {
    
      var obj = {};
    
      obj.title =$('#title').prop('value');
      console.log('title: '+obj.title);
    
      obj.website =$('#website').prop('value');
      console.log('website: '+obj.website);
    
      obj.tags =$('#tags').prop('value').split(',');
      console.log('tags: '+obj.tags);
    
      do_something(JSON.stringify(obj));
    
    }
    

    当然,如果您知道名称是什么,就可以这样做,而且我实际上正在使用formation插件生成表本身。

        4
  •  1
  •   Sean Yang    7 年前

    我用普通的js为这个问题创建了一个例子,请查看开发工具控制台查看数据对象!

    jsfiddle example

    var data = {};
    var array = 'person.name.first'.split('.');
    var value = 'myFirstName';
    generateObj(data, array, value);
    console.log(data);
    
    function generateObj(obj, arr, val) {
        if (arr.length === 1) {
            obj[arr[0]] = val
            return;
        } 
    
        var restArr = arr.splice(1);
        if (!obj[arr[0]]) {
            obj[arr[0]] = {};
        }
        generateObj(obj[arr[0]], restArr, val);
    }
    

    解决方案:

    1. 将每个名称字符串转换为数组。
    2. 遍历每个数组。
    3. 递归调用一个方法,该方法创建一个obj并将此obj设置为属性的值,并将此obj传递给下一个递归。
        5
  •  -1
  •   spender    15 年前

    创建该形状的对象,然后使用 JSON encoder 写出来。