开发者

Javascript serialize form to object

I have form with names 'config[display][x]', 'config[display][y]', 'config[port]',... , or i can create different format. 开发者_如何转开发and i want to serialize it to JS object like

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

Somebody know existing solutions to do it?

p.s. i can serialize form with jQuery's .serializeArray(), but i will have array with simple {name : name, value : value} hashes. But how to create object?


See https://github.com/serbanghita/formToObject - there is also a comparison with existing solutions.

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


I used Ben Almans .serializeObject() and it worked.

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

The code is small and easy:

$.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;
};


To serialize a JavaScript object to a string, use:

var str = JSON.stringify(obj);

To deserialize a string to a JavaScript object, use:

var obj = JSON.parse(str);

If you are using an older browser that does not support these methods, you can use the JSON2 library from Douglas Crockford.


I believe this it what you seek:

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;
};


This is how I do this with nested form names, which can have multiple layers depending on what I have to transmit. I only need this in edge cases, but I thought I'd share this here.

I had the problem that form names were submitted as data[SomeName[hello]][world] = "foobar" which would result in a nasty data structure on php(for example)

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

without checking the data clientside before submitting the serialized data that I only used https://stackoverflow.com/a/48218209/1356107 for, I got these errors when the form data was wrapped into another object.

By checking the code through the hoops to jump through in the snippet below, I resolved the issue and am able to send a complete valid data structure.

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">

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜