【问题标题】:How to convert jQuery.serialize() data to JSON object?如何将 jQuery.serialize() 数据转换为 JSON 对象?
【发布时间】:2011-03-17 16:47:28
【问题描述】:

当表单包含多个输入数组字段时,是否有更好的解决方案来转换已经由 jQuery 函数 serialize() 序列化的表单数据。我希望能够将表单数据转换为 JSON 对象以重新创建其他一些信息表。所以告诉我一个更好的方法将序列化字符串转换为 JSON 对象。

<form id='sampleform'>
    <input name='MyName' type='text' /> // Raf

    <!--array input fields below-->
    <input name='friendname[]' type='text' /> // Bily
    <input name='fiendemail[]' type='text' /> // bily@someemail.com

    <!--duplicated fields below to add more friends -->
    <input name='friendname[]' type='text' /> // Andy
    <input name='fiendemail[]' type='text' /> // Andy@somwhere.com

    <input name='friendname[]' type='text' /> // Adam
    <input name='fiendemail[]' type='text' /> // Adam@herenthere.com
</form>

获取数据的jquery方法

var MyForm = $("#sampleform").serialize();
/** result : MyName=Raf&friendname[]=Billy&fiendemail[]=bily@someemail.com&friendname[]=Andy&fiendemail[]=Andy@somwhere.com&friendname[]=Adam&fiendemail[]=Adam@herenthere.com
*/

如何将这些数据放入 JSON 对象? 它应该具有来自上述表单的以下示例 JSON 数据。

{
    "MyName":"raf",
    "friendname":[
        {"0":"Bily"},
        {"1":"Andy"},
        {"2":"Adam"}
    ],
    "friendemail":[
        {"0":"bily@someemail.com"},
        {"1":"Andy@somwhere.com"},
        {"2":"Adam@herenthere.com"}
    ]
}

【问题讨论】:

  • 从技术上讲,这不是基于您的查询字符串格式化 JSON 对象的方式。具体来说,数组元素不会是具有索引的对象,而只是值。话虽如此,如果您需要发布的格式,您可能需要编写自定义函数。
  • 你可以使用this plugin
  • 感谢 Slaks 和 Jason,是的,我确实同意我需要一个函数来执行此操作,并且 Slaks 已经为我指出了这一点。
  • 2018 人,在回答这个问题几年后,我从这里尝试了多种解决方案,并推荐 tothemario 解决方案:github.com/marioizquierdo/jquery.serializeJSON 即使您使用“对象 [属性]”形式命名你的输入。

标签: javascript jquery json serialization


【解决方案1】:

使用 JSON.stringify() 和 serializeArray():

console.log(JSON.stringify($('#sampleform').serializeArray()));

【讨论】:

    【解决方案2】:

    所有给出的答案都有一些问题是......

    如果输入名称为数组,如name[key],但它会像这样生成

     name:{
       key : value
     }
    

    例如: 如果我有这样的表格。

        <form>
            <input name="name" value="value" >
            <input name="name1[key1]" value="value1" >
            <input name="name2[key2]" value="value2" >
            <input name="name3[key3]" value="value3" >
        </form>
    

    然后它会生成这样的对象,所有给定的答案。

    Object {
        name : 'value',
        name1[key1] : 'value1',
        name2[key2] : 'value2',
        name3[key3] : 'value3', 
    }
    

    但它必须像下面那样生成,任何人都想像下面这样。

    Object {
        name : 'value',
        name1 : {
            key1 : 'value1'
        },
        name2 : {
            key2 : 'value2'
        },
        name3 : {
            key2 : 'value2'
        }
    }
    

    那就试试下面的js代码吧。

    (function($) {
      $.fn.getForm2obj = function() {
        var _ = {};
        $.map(this.serializeArray(), function(n) {
          const keys = n.name.match(/[a-zA-Z0-9_]+|(?=\[\])/g);
          if (keys.length > 1) {
            let tmp = _;
            pop = keys.pop();
            for (let i = 0; i < keys.length, j = keys[i]; i++) {
              tmp[j] = (!tmp[j] ? (pop == '') ? [] : {} : tmp[j]), tmp = tmp[j];
            }
            if (pop == '') tmp = (!Array.isArray(tmp) ? [] : tmp), tmp.push(n.value);
            else tmp[pop] = n.value;
          } else _[keys.pop()] = n.value;
        });
        return _;
      }
      console.log($('form').getForm2obj());
      $('form input').change(function() {
        console.clear();
        console.log($('form').getForm2obj());
      });
    })(jQuery);
    console.log($('form').getForm2obj());
    <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
    <form>
      <input name="name" value="value">
      <input name="name1[key1]" value="value1">
      <input name="name2[key2]" value="value2">
      <input name="name3[key3]" value="value3">
      <input type="checkbox" name="name4[]" value="1" checked="checked">
      <input type="checkbox" name="name4[]" value="2">
      <input type="checkbox" name="name4[]" value="3">
    </form>

    【讨论】:

      【解决方案3】:

      使用归约函数的力量!

      $(form).serializeArray().reduce(function (output, value) {
              output[value.name] = value.value
      
              return output
      }, {})
      

      【讨论】:

      • 这不处理 name="name[]" 形式的输入
      【解决方案4】:

      如果你可以使用 ES6,你可以这样做

      const obj = arr.reduce((acc, {name, value}) => ({...acc, [name]: value}), {})
      

      对于序列化数组来说效果很好。

      【讨论】:

        【解决方案5】:

        如果您使用 ajax 请求,则无需使其 json-object 只有 $('#sampleform').serialize() 工作得很好,或者如果您有其他目的,这是我的解决方案:

        var formserializeArray = $("#sampleform").serializeArray();   
        var jsonObj = {};
        jQuery.map(formserializeArray , function (n, i) {
            jsonObj[n.name] = n.value;
        });
        

        【讨论】:

          【解决方案6】:

          我认为这里有很多很好的答案,我根据这些答案制作了自己的函数。

          function formToJSON(f) {
              var fd = $(f).serializeArray();
              var d = {};
              $(fd).each(function() {
                  if (d[this.name] !== undefined){
                      if (!Array.isArray(d[this.name])) {
                          d[this.name] = [d[this.name]];
                      }
                      d[this.name].push(this.value);
                  }else{
                      d[this.name] = this.value;
                  }
              });
              return d;
          }
          
          //The way to use it :
          $('#myForm').submit(function(){
              var datas = formToJSON(this);
              return false;
          });
          

          好吧,让我基本上解释一下为什么我更喜欢这个解决方案...... 如果您有多个具有相同名称的输入,则所有值都将存储在一个数组中,但如果没有,该值将直接存储为 JSON 中的索引值……这就是它与 Danilo 的不同之处Colasso 的回答,其中返回的 JSON 仅基于数组值...

          因此,如果您有一个名为 content 和多个 authors 的文本区域的表单,此函数将返回给您:

          {
              content : 'This is The Content',
              authors : 
                  [
                      0: 'me',
                      1: 'you',
                      2: 'him',
                  ]
          }
          

          【讨论】:

            【解决方案7】:

            Danilo Colasso's 等效的解决方案,与.serializeArray() 具有相同的优缺点(基本上它使用.reduce 而不是$.each)。

            无需扩展即可实现 S.C. 答案中的额外功能。

            $(selector).serializeArray()
                .reduce(function(accum, item) {
                    // This 'if' allows ignoring some values
                    if (-1 === [ 'ignoreThis', 'andThat' ].indexOf(item.name)) {
                        // This allows ignoring NULL values
                        if (item.value !== null) {
                            accum[item.name] = item.value;
                        }
                    }
                    return accum;
                },
                {
                    // By supplying some initial values, we can add defaults
                    // for, say, disabled form controls.
                    preFilledName:  preFilledValue, // optional
                    defaultName  :  defaultValue    // optional
                }
            );
            

            【讨论】:

            • 感谢您教我如何使用 reduce。我正在收藏它并分享它。
            【解决方案8】:
            var formdata = $("#myform").serializeArray();
            
            var data = {};
            
            $(formdata ).each(function(index, obj){
            
                     if(data[obj.name] === undefined)
                          data[obj.name] = [];
            
                      data[obj.name].push(obj.value);
            
            });
            

            【讨论】:

            • 虽然这段代码 sn-p 可以解决问题,但including an explanation 确实有助于提高帖子的质量。请记住,您正在为将来的读者回答问题,而这些人可能不知道您的代码建议的原因。也请尽量不要用解释性的 cmets 挤满你的代码,这会降低代码和解释的可读性!
            【解决方案9】:

            我正在使用这个非常小的 jQuery 插件,它是从 DocumentCloud 扩展而来的:

            https://github.com/documentcloud/documentcloud/blob/master/public/javascripts/lib/jquery_extensions.js

            它基本上是两行代码,但它需要 _.js (Underscore.js),因为它基于 reduce 函数。

            $.fn.extend({
              serializeJSON: function(exclude) {
                exclude || (exclude = []);
                return _.reduce(this.serializeArray(), function(hash, pair) {
                  pair.value && !(pair.name in exclude) && (hash[pair.name] = pair.value);
                  return hash;
                }, {});
              }
            });
            

            扩展:

            • 如果输入值为 null,则不会序列化它
            • 它可以通过将输入名称数组传递给exclude 参数i.e. ["password_confirm"] 来排除某些输入

            【讨论】:

            • 可爱,完美地完成了这项工作!
            【解决方案10】:
            var formdata = $("#myform").serializeArray();
            var data = {};
            $(formdata ).each(function(index, obj){
                data[obj.name] = obj.value;
            });
            

            简单快速;)

            【讨论】:

            • 这不会生成分层的 JS 对象
            • @Epoc 你指的是什么层次的概念?表单数据是扁平的。
            • var formdata = $("#myform").serializeArray(); formdata = JSON.parse(formdata); //添加这一行 var data = {}; $(formdata ).each(function(index, obj){ data[obj.name] = obj.value; });
            • 警告:如果您有多个具有相同键的值(允许在表单中),这将不会保留它们并覆盖同名值
            【解决方案11】:

            使用jQuery.serializeJSON 插件。 它使用与 Rails 参数对象中相同的格式转换表单,这是非常标准且经过良好测试的。

            【讨论】:

              【解决方案12】:

              使用下划线和 jQuery

              var formdata = $("#myform").serializeArray();
              var data = {};
              _.each(formdata, function(element){
              // Return all of the values of the object's properties.
                var value = _.values(element);
              // name : value 
                data[value[0]] = value[1];
              });
              console.log(data); //Example => {name:"alex",lastname:"amador"}
              

              【讨论】:

                【解决方案13】:

                我最近遇到了这个确切的问题。最初,我们使用 jQuery 的 serializeArray() 方法,但不包括禁用的表单元素。我们经常会禁用与页面上其他源“同步”的表单元素,但我们仍然需要将数据包含在我们的序列化对象中。所以serializeArray() 出来了。我们使用:input 选择器获取给定容器中的所有输入元素(启用和禁用),然后使用$.map() 创建我们的对象。

                var inputs = $("#container :input");
                var obj = $.map(inputs, function(n, i)
                {
                    var o = {};
                    o[n.name] = $(n).val();
                    return o;
                });
                console.log(obj);
                

                请注意,要使其正常工作,您的每个输入都需要一个 name 属性,该属性将是结果对象的属性名称。

                这实际上是对我们使用的内容进行了轻微修改。我们需要创建一个结构为 .NET IDictionary 的对象,所以我们使用了这个:(我在这里提供它以防它有用)

                var obj = $.map(inputs, function(n, i)
                {
                    return { Key: n.name, Value: $(n).val() };
                });
                console.log(obj);
                

                我喜欢这两种解决方案,因为它们是 $.map() 函数的简单用法,并且您可以完全控制您的选择器(因此,您最终会在结果对象中包含哪些元素)。此外,不需要额外的插件。普通的旧 jQuery。

                【讨论】:

                • 我刚刚注意到您使用“friendname[]”作为输入元素的名称,以捕获一组值而不是单个值。我认为'$.map()' 不会很好地解决这个问题。
                • 我认为您的地图功能不太正确...您为每个属性返回一个单独的对象...不要'您想将所有属性放在一个对象上?...所以声明函数外部的对象,而不是内部的对象(并且不返回任何内容 - 仅将 map 用于副作用)
                • +1;这个解决方案很棒。我只是参数化了你有#container的部分,而不是调用console.log(),而是把顶部放在一个函数中。
                • 必须将 $(n).val() 更改为 $(n).value
                猜你喜欢
                • 2011-05-20
                • 2011-09-28
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多