Skip to content Skip to sidebar Skip to footer

How To Create A Nested Object (json) Of A Form Input Values Based On The Input Name In Vanilla Javascript?

//lets say the form is like below

Solution 1:

You can use jQuery and use the serializeArray() method like this var jsonData = $('form').serializeArray();:

It doesn't match your sample object but it does what your question asked.

Once you have the fields in an Array you can manipulate your object however you want. I can't quite follow the logic of how you could ever arrive with that object from the form name attributes so I can't even attempt to map it.

<scriptsrc="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><formid="myform"><inputname="foo"value="parent"/><inputname="foo.cat.bar"value="child1"/><inputname="foo.cat.biz"value="child2"/><inputname="foo.cat.biz.dog.bar"value="child3"/></form><inputid='btnSerialize'value='Serialize'type='button'onclick='serializeForm()' /><divid='result'></div><script>functionserializeForm()
  {
    var jsonData = $('form').serializeArray();
    var jsonString = JSON.stringify(jsonData);
    $('#result').html(jsonString);
  }

  </script>

If you change your form names so you can have a valid logical structure than in Plain javascript:

/*
{
  "foo": {
    "bar": "parent",
    "biz": "parent",
    "cat": {
      "bar": "child2achild2a,child2b",
      "biz": {
        "dog": {
          "bar": "child3"
        }
      }
    }
  }
}
*/
<formid="myform"><inputname="foo.bar"value="parent" /><inputname="foo.biz"value="parent" /><inputname="foo.cat.bar"value="child2a" /><inputname="foo.cat.bar"value="child2b" /><inputname="foo.cat.biz.dog.bar"value="child3" /></form><script>functionserialize() {
    var elements = document.querySelectorAll('#myform input');
    var data = {};
    for (var i = 0; i < elements.length; i++) {
      var el = elements[i];
      var val = el.value;
      if (!val) val = "";
      var fullName = el.getAttribute("name");
      if (!fullName) continue;
      var fullNameParts = fullName.split('.');
      var prefix = '';
      var stack = data;
      for (var k = 0; k < fullNameParts.length - 1; k++) {
        prefix = fullNameParts[k];
        if (!stack[prefix]) {
          stack[prefix] = {};
        }
        stack = stack[prefix];
      }
      prefix = fullNameParts[fullNameParts.length - 1];
      if (stack[prefix]) {

        var newVal = stack[prefix] + ',' + val;
        stack[prefix] += newVal;
      } else {
        stack[prefix] = val;
      }
    }
    console.log(data);

  }
</script><inputtype="button"value="go"onclick="serialize()" /><p><br /></p><p><br /></p>

Solution 2:

Here you go. I've included an explanation in the comments...

functiongetFormData() {
    /* return nested array combined
       into groups of two. See question @ 
       https://stackoverflow.com/a/31352555/4746328 */functiongroupIntoPairs(arr) {
        var temp = arr.slice();
        var out = [];

        while (temp.length) {
            out.push(temp.splice(0,2));
        }

        return out;
    }

    /* create a storage object */var data = {},
    /* get 'input' elements as an array */
    inputs = [].slice.call(document.getElementById('myform').querySelectorAll('input')),
    /* additional variables */
    name, hold, splits, L, dKey;

    /* loop through input elements */
    inputs.forEach(function(n) {
        name = n.name;

        /* for holding key strings */
        hold = '';

        /* split the 'name' at '.'
           and group into pairs */ 
        splits = groupIntoPairs( name.split('.') );

        /* index of last item in 'splits' */
        L = splits.length - 1;

        /* if 'splits' has only one
           item add the name-value pair
           to 'data' straight away */if (L === 0) {
            data[name] = n.value;
        } else {
            /* loop 'splits' to create keys */
            splits.forEach(function(x, i) {
                /* combine key strings until
                   last item in 'splits' */if (i !== L) hold += '.' + x.join('.');
            });

            /* define the key */
            dKey = hold.slice(1);

            /* create 'data[dKey]' Object if
               it doesn't exist or use it
               again if it does */
            data[dKey] = data[dKey] || {};

            /* add last item in 'splits' as 
               key for 'data[dKey]' and 
               assign current n.value */
            data[dKey][splits[L][0]] = n.value;                
        }
    });
    /* return 'data' object */return data;
}

console.log('data:', JSON.stringify(getFormData(), null, 4));
/* => data: {
    "foo": "parent",
    "foo.cat": {
        "bar": "child1",
        "biz": "child2"
    },
    "foo.cat.biz.dog": {
        "bar": "child3"
    }
}
*/

Hope that helped.

Post a Comment for "How To Create A Nested Object (json) Of A Form Input Values Based On The Input Name In Vanilla Javascript?"