将FORM层次结构反序列化为JS对象

时间:2016-02-16 12:54:30

标签: javascript jquery arrays object serialization

我有一个表单,其控件的名称代表层次结构

实施例



<form>
    <input name="[field1][0][field11]" value="foobar1" />
    <input name="[field1][0][field12][0][field121]" value="foobar2" />
    <input name="[field2]" value="foobar3" />
    <input name="[field3][0][field31]" value="foobar4" />
    <input name="[field3][1][field32][0][field321]" value="foobar5" />
</form>
&#13;
&#13;
&#13;

我想获得一个代表层次结构的 Object ,如下所示:

&#13;
&#13;
{
    "field1": [
        {
            "field11": "foobar1",
            "fiedl12": [
                {
                    "field121": "foobar2"
                }
            ]
        }
    ],
    "field2": "foobar3",
    "field3": [
        {
            "field31": "foobar4"
        },
        {
            "field32": [
                {
                    "field321": "foobar5"
                }
            ]
        }
    ]
}
&#13;
&#13;
&#13;

如何获得?是否有任何本机JS或 jQuery 功能来实现这一目标? ( .serializeArray()在这里没有帮助)

只是名称结构是标准的,实际名称不会包含 field- 12 field- 321 <等索引/ em>(唯一的索引是模式的第二个方括号&#34; [field] [index] &#34;。

[field] 对应一个普通的字符串值(当没有 [index] 时)或一个数组(当 [index] 在那里。

[index] 始终对应于新的对象{}),其中包含以下[] - 括号集中定义的属性。< / p>

PS - 请不要 jQuery 插件

2 个答案:

答案 0 :(得分:0)

不太难。首先获取一个元素数组,拆分名称,然后递归地将它们放入一个对象中。然后输出对象,你就会听到你想要的声音。

我承认,这是非常混乱的,我猜你可能有更好的方法去做你想做的事情。无论哪种方式,下面的代码都适用于您所描述的内容。

注意:这使用没有Jquery或其他库的普通javascript。

function organizeInputs() {
  var inputs = document.getElementsByTagName('input');  // Get all input elements
  var output = {};
  for (var i=0;i<inputs.length;i++) {           // Iterate through elements
    var keys = inputs[i].name  // Split and format element names to keys
      .split("]")
      .map(function(str) {
        return str.replace("[", "");
      }).filter(function(str) {
        return str.length > 0;
      });
    fillObj(output, keys, inputs[i].value);  // Recursively add to object using keys
  }
  return output;
}

function fillObj(obj, arr, val) {  // Recursively add to object passed
  if (arr.length == 1)
    return obj[arr[0]] = val;
  if (!obj[arr[0]])
    if (arr.length > 1) {
      if (isNaN(arr[1])) {
        obj[arr[0]] = {};
      } else {
        obj[arr[0]] = [];
      }
    } else {
      obj[arr[0]] = {};
    }
  return fillObj(obj[arr[0]], arr.slice(1, arr.length), val);
}

//  To use run organizeInputs()

//  Just for display
var out = document.createTextNode(JSON.stringify(organizeInputs(), null, 2));
document.getElementById("result").appendChild(out);
<form>
  <input name="[field1][0][field11]" value="foobar1" />
  <input name="[field1][0][field12][0][field121]" value="foobar2" />
  <input name="[field2]" value="foobar3" />
  <input name="[field3][0][field31]" value="foobar4" />
  <input name="[field3][1][field32][0][field321]" value="foobar5" />
</form>
<pre id="result"></pre>

答案 1 :(得分:0)

它看起来并不那么容易。收集所有元素,解析名称并使用数组或对象子级上的不同视图迭代新对象。然后申请价值。

function getForm(form, object) {
    var a, e = form.elements, i, l;
    for (i = 0; i < e.length; i++) {
        a = e[i].name.match(/([^\[\]]|\[\])+/g);
        l = a.pop();
        a.reduce(function (r, k, j) {
            r[k] = r[k] || (isFinite(a[j + 1] || l) ? [] : {});
            return r[k];
        }, object)[l] = e[i].value;
    }
}

var object = {};
getForm(document.forms.form1, object);
document.write('<pre>' + JSON.stringify(object, 0, 4) + '</pre>');
<form name="form1">
    <input name="[field1][0][field11]" value=" foobar1" />
    <input name="[field1][0][field12][0][field121]" value="foobar2" />
    <input name="[field2]" value="foobar3" />
    <input name="[field3][0][field31]" value="foobar4" />
    <input name="[field3][1][field32][0][field321]" value="foobar5" />
</form>