将多维输入转换为JavaScript对象

3
我已经尝试解决这个问题几天了,但是它让我感到非常困扰。我有一些需要通过Ajax提交的数据。它是动态的,因此我不知道它有多少个字段。此外,字段的名称是多维的,也是动态的。例如,一个输入框可能具有名称为data[name]data[title]的字段,而另一个更大的输入框可能具有data[images][0][src]data[images][0][alt]data[images][0][description]data[images][1][src]data[images][1][alt]data[images][1][description]等,其中数组中的元素数量未知。我的问题是,我需要获取一个可以通过Ajax提交的对象,同时保持数据的结构。
我尝试过对数据进行序列化,但那只会得到一个name = value的字符串。我也尝试过序列化数组,但那只会给我一个[name, value]的数组。我成功使用正则表达式手动生成了对象,但我找不到将结果对象合并在一起的方法。我的最新代码版本如下:
$('.modal-content').find('input[name^="data"]').each(function () {
    var found = $(this).attr('name').match(re).reverse();
    var temp = $(this).val();
    $.each(found, function ()
    {
        str = this.substr(1, this.length - 2);
        var t = {};
        t[str] = temp;
        temp = t;
    });
    data = $.each({}, data, temp);
});

很不幸,它并不会合并它们,而是用temp中的内容覆盖了data中的内容。如果data有data.images[0].src = "mysrc",而temp有data.images[0].alt = "myalt",那么最终我只得到data.images[0].alt = "myalt",src便不再存在。

肯定有一个简单的方法来解决这个问题,现在,我甚至可以采用复杂的方法来解决这个问题。请有人能帮助我吗?


1
HTML本身是什么样子的?它是动态的,但它是否遵循一定的模式呢? - Rory McCrossan
@RoryMcCrossan 唯一的共同点是它们都在一个带有ID的div中,并且它们都遵循模式name="data[x][y][z],其中xyz是动态的,而且有未知数量的段落。有些将是文本输入框,其他是单选按钮,有些是下拉选择框,其他是文本区域(我知道目前只处理输入,一旦输入正常,将调整代码)。 - Styphon
实际的HTML代码非常冗长,因此我在这里粘贴了我目前拥有的最复杂版本的副本 - http://pasted.co/0643034a - Styphon
@timster 它需要看起来像名称的数组结构。因此,如果输入名称为data[images][0][src],我需要JSON为{data:{images[{src: value}]}} - Styphon
@matheusr 不确定您是否理解问题。 我已经在一个对象中获得了正确的结构,但问题是合并多个对象而不覆盖以前的条目。 如果我尝试将{data:{images[{src:value}]}}{data:{images[{alt:value}]}}合并,则无法像预期的那样得到{data:{images[{src:value,alt:value}]}}src: value会被覆盖。 - Styphon
显示剩余2条评论
2个回答

2

虽然已经有一个被接受的答案了,但是我想提出我的5分建议:

在我看来,应该尽可能避免使用正则表达式。因此,我的建议是稍微修改一下HTML代码,在包含图像的div中添加一些类,并更改输入框的名称属性:

<li class="col-xs-12 col-sm-6 col-md-4 col-lg-3 gallery-image ui-sortable-handle">
        <div class="my-image">
            <img src="http://localhost:8000/img/example.jpg">
            <input type="hidden" name="src" value="img/example.jpg">
            <div class="form-group">
                <label for="title-0">Title:</label>
                <input type="text" name="title" class="form-control" id="title-0" value="Default Example Image 1" placeholder="Title">
            </div>
            <div class="form-group">
                <label for="description-0">Description:</label>
                <input type="text" name="description" class="form-control" id="description-0" value="A default example image." placeholder="Description">
            </div>
            <div class="form-group">
                <label for="alt-0">Alt tag (SEO):</label>
                <input type="text" name="alt" class="form-control" id="alt-0" value="fluid gallery example image" placeholder="Alt tag">
            </div>
            <div class="form-group">
                <label for="order-0">Order:</label>
                <input type="number" name="order" class="form-control image-order" id="order-0" value="0">
            </div>
            <button type="button" class="btn btn-danger remove-gallery-image-btn">× Delete</button>
        </div>
    </li>
    <li class="col-xs-12 col-sm-6 col-md-4 col-lg-3 gallery-image ui-sortable-handle">
        <div class="my-image">
            <img src="http://localhost:8000/img/example.jpg">
            <input type="hidden" name="src" value="img/example.jpg">
            <div class="form-group">
                <label for="title-1">Title:</label>
                <input type="text" name="title" class="form-control" id="title-1" value="Default Example Image 2" placeholder="Title">
            </div>
            <div class="form-group">
                <label for="description-1">Description:</label>
                <input type="text" name="description" class="form-control" id="description-1" value="A default example image." placeholder="Description">
            </div>
            <div class="form-group">
                <label for="alt-1">Alt tag (SEO):</label>
                <input type="text" name="alt" class="form-control" id="alt-1" value="fluid gallery example image" placeholder="Alt tag">
            </div>
            <div class="form-group">
                <label for="order-1">Order:</label>
                <input type="number" name="order" class="form-control image-order" id="order-1" value="1">
            </div>
            <button type="button" class="btn btn-danger remove-gallery-image-btn">× Delete</button>
        </div>
    </li>

然后构建与该类匹配的对象:

var obj = {
  data: {
    images: []
  }
}

var groups = $('.my-image');

groups.each(function(idx, el) {
  var child = {}
  $(el).find('input').each(function(jdx, info){
    var $info = $(info);
    child[$info.attr('name')] = $info.val();
  });

  obj.data.images.push(child);
});

我们可以得到相同的结果,但可能会减少错误。这是一个plunker示例链接。

谢谢你的输入,但那正是我不想要做的。因为输入是动态的,我必须为每种不同类型写多次代码。我不想为图像、视频、纯文本、横幅等分别编写代码。使用正则表达式,它可以处理动态内容,无论我有哪些输入字段,只要它们以"data"开头,它就可以正常工作。 - Styphon

1
你可以使用 each() 循环遍历所有的 inputs,使用 split()name 属性中创建数组,然后使用 reduce 将其添加到对象中。

var result = {}

$('input').each(function() {
  var name = $(this).attr('name');
  var val = $(this).val();

  var ar = name.split(/\[(.*?)\]/gi).filter(e => e != '');

  ar.reduce(function(a, b, i) {
    return (i != (ar.length - 1)) ? a[b] || (a[b] = {}) : a[b] = val;
  }, result)

})

console.log(result)
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="gallery-images" class="ui-sortable">
  <li class="col-xs-12 col-sm-6 col-md-4 col-lg-3 gallery-image ui-sortable-handle">
    <div>
      <img src="http://localhost:8000/img/example.jpg">
      <input type="hidden" name="data[images][0][src]" value="img/example.jpg">
      <div class="form-group">
        <label for="title-0">Title:</label>
        <input type="text" name="data[images][0][title]" class="form-control" id="title-0" value="Default Example Image 1" placeholder="Title">
      </div>
      <div class="form-group">
        <label for="description-0">Description:</label>
        <input type="text" name="data[images][0][description]" class="form-control" id="description-0" value="A default example image." placeholder="Description">
      </div>
      <div class="form-group">
        <label for="alt-0">Alt tag (SEO):</label>
        <input type="text" name="data[images][0][alt]" class="form-control" id="alt-0" value="fluid gallery example image" placeholder="Alt tag">
      </div>
      <div class="form-group">
        <label for="order-0">Order:</label>
        <input type="number" name="data[images][0][order]" class="form-control image-order" id="order-0" value="0">
      </div>
      <button type="button" class="btn btn-danger remove-gallery-image-btn">× Delete</button>
    </div>
  </li>
  <li class="col-xs-12 col-sm-6 col-md-4 col-lg-3 gallery-image ui-sortable-handle">
    <div>
      <img src="http://localhost:8000/img/example.jpg">
      <input type="hidden" name="data[images][1][src]" value="img/example.jpg">
      <div class="form-group">
        <label for="title-1">Title:</label>
        <input type="text" name="data[images][1][title]" class="form-control" id="title-1" value="Default Example Image 2" placeholder="Title">
      </div>
      <div class="form-group">
        <label for="description-1">Description:</label>
        <input type="text" name="data[images][1][description]" class="form-control" id="description-1" value="A default example image." placeholder="Description">
      </div>
      <div class="form-group">
        <label for="alt-1">Alt tag (SEO):</label>
        <input type="text" name="data[images][1][alt]" class="form-control" id="alt-1" value="fluid gallery example image" placeholder="Alt tag">
      </div>
      <div class="form-group">
        <label for="order-1">Order:</label>
        <input type="number" name="data[images][1][order]" class="form-control image-order" id="order-1" value="1">
      </div>
      <button type="button" class="btn btn-danger remove-gallery-image-btn">× Delete</button>
    </div>
  </li>
  <li class="col-xs-12 col-sm-6 col-md-4 col-lg-3 gallery-image ui-sortable-handle">
    <div>
      <img src="http://localhost:8000/uploads/galleries\21\4-tux-30.jpg">
      <input type="hidden" name="data[images][2][src]" value="uploads/galleries\21\4-tux-30.jpg">
      <div class="form-group">
        <label for="title-2">Title:</label>
        <input type="text" name="data[images][2][title]" class="form-control" id="title-2" value="" placeholder="Title">
      </div>
      <div class="form-group">
        <label for="description-2">Description:</label>
        <input type="text" name="data[images][2][description]" class="form-control" id="description-2" value="" placeholder="Description">
      </div>
      <div class="form-group">
        <label for="alt-2">Alt tag (SEO):</label>
        <input type="text" name="data[images][2][alt]" class="form-control" id="alt-2" value="" placeholder="Alt tag">
      </div>
      <div class="form-group">
        <label for="order-2">Order:</label>
        <input type="number" name="data[images][2][order]" class="form-control image-order" id="order-2" value="2">
      </div>
      <button type="button" class="btn btn-danger remove-gallery-image-btn">× Delete</button>
    </div>
  </li>
  <li class="col-xs-12 col-sm-6 col-md-4 col-lg-3 gallery-image ui-sortable-handle">
    <div>
      <img src="http://localhost:8000/uploads/galleries\21\all-free-backgrounds-simple-style-darkblue-18.jpg">
      <input type="hidden" name="data[images][3][src]" value="uploads/galleries\21\all-free-backgrounds-simple-style-darkblue-18.jpg">
      <div class="form-group">
        <label for="title-3">Title:</label>
        <input type="text" name="data[images][3][title]" class="form-control" id="title-3" value="" placeholder="Title">
      </div>
      <div class="form-group">
        <label for="description-3">Description:</label>
        <input type="text" name="data[images][3][description]" class="form-control" id="description-3" value="" placeholder="Description">
      </div>
      <div class="form-group">
        <label for="alt-3">Alt tag (SEO):</label>
        <input type="text" name="data[images][3][alt]" class="form-control" id="alt-3" value="" placeholder="Alt tag">
      </div>
      <div class="form-group">
        <label for="order-3">Order:</label>
        <input type="number" name="data[images][3][order]" class="form-control image-order" id="order-3" value="3">
      </div>
      <button type="button" class="btn btn-danger remove-gallery-image-btn">× Delete</button>
    </div>
  </li>
</ul>


非常感谢!它起作用了!我以前从未听说过reduce。那正是我所需要的。 - Styphon
不客气,您可以在这里阅读更多相关信息:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce - Nenad Vracar
我在 filter 中使用了箭头函数,这是ES6的语法,如果你需要支持旧版浏览器,可以像这样编写 https://jsfiddle.net/Lg0wyt9u/1318/ - Nenad Vracar
谢谢,我已更新我的代码,以便它能够与旧版浏览器一起使用。 - Styphon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接