【问题标题】:Javascript serialize form to objectJavascript将表单序列化为对象
【发布时间】:2011-09-10 22:23:48
【问题描述】:

我有名称为 'config[display][x]', 'config[display][y]', 'config[port]',... 的表单,或者我可以创建不同的格式。 我想将它序列化为 JS 对象,如

{config:
    display : {x : 'value', y : 'value'},
    port : 'value'
}

有人知道现有的解决方案吗?

附言我可以使用 jQuery 的 .serializeArray() 序列化表单,但我将拥有带有简单 {name:name,value:value} 哈希的数组。但是如何创建对象呢?

【问题讨论】:

  • 对于其他错过它的人,Zach 的回答是一个很好的候选人。

标签: javascript forms serialization


【解决方案1】:

要将 JavaScript 对象序列化为字符串,请使用:

var str = JSON.stringify(obj);

要将字符串反序列化为 JavaScript 对象,请使用:

var obj = JSON.parse(str);

如果您使用的是不支持这些方法的旧版浏览器,则可以使用 Douglas Crockford 的 JSON2 库。

【讨论】:

  • 和?表单名称 - 只是字符串
【解决方案2】:

我使用了 Ben Almans .serializeObject(),它奏效了。

http://benalman.com/projects/jquery-misc-plugins/#serializeobject

代码小而简单:

$.fn.serializeObject = function(){
    var obj = {};

    $.each( this.serializeArray(), function(i,o){
        var n = o.name,
        v = o.value;

        obj[n] = obj[n] === undefined ? v
            : $.isArray( obj[n] ) ? obj[n].concat( v )
            : [ obj[n], v ];
    });

    return obj;
};

【讨论】:

  • 这不会正确序列化数组和嵌套属性。
【解决方案3】:

我相信这就是你所寻求的:

function assignByPath(obj,path,value){
    if (path.length == 1) {
        obj[path[0]] = value;
        return obj;
    } else if (obj[path[0]] === undefined) {
        obj[path[0]] = {};
    } 
    return assignByPath(obj[path.shift()],path,value);
}

$.fn.serializeObject = function(){
    var obj = {};

    $.each( this.serializeArray(), function(i,o){
        var n = o.name,
        v = o.value;
        path = n.replace('[','.').replace('][','.').replace(']','').split('.');

        assignByPath(obj,path,v);
    });

    return obj;
};

【讨论】:

    【解决方案4】:

    参见https://github.com/serbanghita/formToObject - 还与现有解决方案进行了比较。

    var myFormObj = formToObject('myFormId');
    /* 
      console.log(myFormObj);
      {
        saveSettings: 'Save',
        name: 'Serban',
        race: 'orc',
        settings: {
           input: 'keyboard',
           video: {
              resolution: '1024x768',
              vsync: 'on'
           }
        }
      }
    */
    

    【讨论】:

    • 目前,如果您想使用数组,github.com/serbanghita/formToObject.js/issues/17 会妨碍您。
    • @Xr。同意,这就是我决定拆开图书馆并对其进行单元测试的原因。我需要回归来解决这个问题。我需要解决这个问题,因为在 JavaScript 中你不能有一个带有文字键的数组。感谢您的反馈!
    【解决方案5】:

    这就是我使用嵌套表单名称执行此操作的方式,根据我必须传输的内容,它可以具有多个层。我只在极端情况下需要这个,但我想我会在这里分享这个。

    我遇到了表单名称以data[SomeName[hello]][world] = "foobar" 提交的问题,这会导致 php 上出现令人讨厌的数据结构(例如)

    $data = [
       "data" => [
         "SomeName[hello" => [
             "world" => "foobar"
         ],
      ],
    ];
    

    在提交我仅使用https://stackoverflow.com/a/48218209/1356107 的序列化数据之前未检查数据客户端,当表单数据被包装到另一个对象时出现这些错误。

    通过检查代码以跳过下面的 sn-p,我解决了问题并能够发送完整的有效数据结构。

    getFormData = function($form) 
    {    	
      var paramObj = {};
      /**
        * Credit where credit is due. Copied from https://stackoverflow.com/a/48218209/1356107 by jhildenbiddle
        */
      var mergeDeep = function(...objects) 
      {
        var isObject = obj => obj && typeof obj === 'object';
        return objects.reduce((prev, obj) => {
          Object.keys(obj).forEach(key => {
            var pVal = prev[key];
            var oVal = obj[key];
    
            if (Array.isArray(pVal) && Array.isArray(oVal)) {
              prev[key] = pVal.concat(...oVal);
            }
            else if (isObject(pVal) && isObject(oVal)) {
              prev[key] = mergeDeep(pVal, oVal);
            }
            else {
              prev[key] = oVal;
            }
          });
    
          return prev;
        }, {});
      }
      var phpFormKeyToObject = function(key, value) 
      {
        var lookup = key.indexOf('[');
        if(lookup != -1) {
          var arrayName = key.substring(0, lookup);
          var newObj = {};
          newObj[arrayName] = {};
          var res = key.matchAll(/\[(.*?)\]/g);
          var previous = newObj[arrayName];       
          var lastkey = arrayName; 
          var lastobj = newObj;
          for(var match of res) {
            /** 
             * Arrays exit early. zero length key, is array, append and exit.
             */
            if(match[1].length == 0) {
              if(Array.isArray(lastobj[lastkey])) {
                lastobj[lastkey].push(value);
                return newObj;
              }
              else {
                lastobj[lastkey] = [value];
                return newObj;
              }
            }
            else {
              previous[match[1]] = {};
              lastobj = previous;
              previous = previous[match[1]];
              lastkey = match[1];
            }
          }
          lastobj[lastkey] = value;
          return newObj;
        }
        return false;
      }
      /** 
       * Credit where credit is due, slightly modified version of https://stackoverflow.com/a/2403206/1356107 by Pointy
       */  
      $.each($form.serializeArray(), function(_, kv) {
        if(kv.name.indexOf('[') != -1) {
          var obj = phpFormKeyToObject(kv.name, kv.value);
          paramObj = mergeDeep(paramObj, obj);
        }
        else {
          if (paramObj.hasOwnProperty(kv.name)) {
            paramObj[kv.name] = $.makeArray(paramObj[kv.name]);
            paramObj[kv.name].push(kv.value);
          }
          else {
            paramObj[kv.name] = kv.value;
          }
        }
      });
      return paramObj;
    }
      
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <form id="testform">
      <label>check it 1</label><input type="checkbox" value="1" name="SomeName[checkboxvalues][]"><BR/>
      <label>check it 2</label><input type="checkbox" value="2" name="SomeName[checkboxvalues][]"><BR/>
      <label>check it 3</label><input type="checkbox" value="3" name="SomeName[checkboxvalues][]"><BR/>
      <label>test</label><input type="text" value="test" name="SomeName[test]"><BR/>
      <label>how much of extra 1</label>
      <select name="SomeName[extra_items][320]">
        <option value="1">1</option>
        <option value="2">2</option>
        <option value="3">3</option>
      </select><br/>
      <label>how much of extra 2</label>
      <select name="SomeName[extra_items][321]">
        <option value="1">1</option>
        <option value="2">2</option>
        <option value="3">3</option>
      </select><BR/>
      <input type="hidden" name="somehiddenvalue" value="this is hidden">
      <input type="button" onclick="console.log(getFormData($('#testform')))" value="test me">

    【讨论】:

      猜你喜欢
      • 2014-08-08
      • 1970-01-01
      • 1970-01-01
      • 2011-09-23
      • 1970-01-01
      • 2016-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多