6

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?

3
  • For others that missed it, answer from Zach is a great candidate. Commented Nov 21, 2020 at 8:39
  • @OverMars No it isn't. The question has nothing do do with JSON. Commented Jan 20, 2024 at 0:09
  • Does this answer your question? Convert form data to JavaScript object with jQuery Commented Jan 20, 2024 at 1:31

5 Answers 5

4

See my library 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'
       }
    }
  }
*/
Sign up to request clarification or add additional context in comments.

2 Comments

Currently, github.com/serbanghita/formToObject.js/issues/17 gets in the way if you want to use arrays.
@Xr. agree, this is why I decided to tear the library apart and unit test it. I need regression in order to fix this. I need to sort this out since in JavaScript you cannot have an array with literal keys. Thanks for the feedback!
1

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

1 Comment

This doesn't serialize arrays and nested properties properly.
1

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

Comments

0

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.

2 Comments

and? form names - just strings
The question has nothing to do with JSON.
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.