23

我正在尝试转换此 HTML 表:

在此处输入图像描述

代码:

<table id="students" border="1">
    <thead>
        <tr>
            <th>Name</th>
            <th>Age</th>
            <th>Grade</th>
        </tr>
    </thead>
    <tbody>
        <tr class="student">
            <td>Oscar</td>
            <td>23</td>
            <td>16.5</td>        
        </tr>
        <tr class="student">
            <td>Antonio</td>
            <td>32</td>
            <td>14</td>        
        </tr>
        <tr class="student">
            <td>Jessica</td>
            <td>21</td>
            <td>19</td>        
        </tr>
    </tbody>
</table>​​​​​​

使用 jQuery 进入 javascript 对象:

var tbl = $('table#students tr').map(function() {
  return $(this).find('td').map(function() {
    return $(this).text();
  }).get();
}).get();

上面的代码将输出以下数组:

["Oscar", "23", "16.5", "Antonio", "32", "14", "Jessica", "21", "19"]

此时一切都很好,但是如果我希望数组中的 javascript 对象具有以下结构,我该怎么办:

[{id:1, name: "Oscar", age: 23, grade: 16.5}, {id:2, name: "Antonio", age: 32, grade: 14}, {id:3, name: "Jessica", age: 21, grade: 19}]

在此处输入图像描述

只是为了更具体.​​..

  • idtr
  • ,name和值是从每一行获得agegrade

我做了这个jsfiddle来测试:

http://jsfiddle.net/oscarj24/ptVDm/

谢谢

4

6 回答 6

31
var tbl = $('#students tr:has(td)').map(function(i, v) {
    var $td =  $('td', this);
        return {
                 id: ++i,
                 name: $td.eq(0).text(),
                 age: $td.eq(1).text(),
                 grade: $td.eq(2).text()               
               }
}).get();

于 2012-09-05T23:13:05.753 回答
10

我需要这个确切的东西,除了我需要更多功能来覆盖列名并忽略任何隐藏的行。我写了一个 jQuery 插件来做到这一点,位于https://github.com/lightswitch05/table-to-json

对于你的例子,你会做:(http://jsfiddle.net/ptVDm/118/

var table = $('#students').tableToJSON();

需要注意的一件事是 id 不是结果对象的一部分。您可以从对象的数组位置获取 id。或者,如果您真的需要它成为对象的一部分,您可以为 ID 创建一个隐藏列,然后将它们包含在内

于 2013-02-13T18:28:10.047 回答
8

以下应该有效:

var cols = [];
var result = [];
$('#students>thead>th').each(function(){
    cols.push($(this).text().toLowerCase());
});
$('#students>tbody>tr').each(function(id){
    var row = {'id': id+1};
    $(this).find('td').each(function(index){
        row[cols[index]] = $(this).text();
    });
    result.push(row);
});

console.log(result);

基本上,我从表头找到对象属性,接下来我为每一行创建一个对象,将值分配给从前面的数组推导出的属性名称。

一些明显的缺陷:

  • 如果表格数据由于某种原因实际上不同(例如,化妆品的空行),该系统会将空对象放入结果数组中。
  • 如果colspan在表中使用属性,本系统不会自动在不同的对象属性中复制相同的值,而是限制设置为剩余<td>的 s。

看到 Josiah 的方法,它可能比我的更快,因为我试图通过查找属性名称来变得更聪明。如果你确定你的表结构不会改变,我会推荐他的技术。否则,您将需要我的代码行中的某些内容。

哦,为了完整起见,这是我的 JSFiddle

于 2012-09-05T23:07:47.450 回答
4

请参阅更新的小提琴。额外的数组map是不必要的,因为此时您正在为 JSON 寻找文字对象。

var data = $('table#students tbody tr').map(function(index) {
    var cols = $(this).find('td');
    return {
        id: index + 1,
        name: cols[0].innerHTML,            // use innerHTML
        age: (cols[1].innerHTML + '') * 1,  // parse int
        grade: (cols[2].innerHTML + '') * 1 // parse int
    };
}).get();
于 2012-09-05T23:12:00.720 回答
2

不知道 jQuery 在这种情况下是否有很大帮助,这是一个简单的 JS 解决方案,它合理地独立于表结构。它只要求第一行是标题(可以是不同的表格部分元素或不是),并且行 1+ 是数据。

该表可以有任意多的列或行,如果其中有行跨度或列跨度,它会弄乱结果(但 jQuery 也不会帮助你)。

它可以很容易地调整为专门使用属性名称的标题部分并忽略页脚部分:

function tableToObj(table) {
  var rows = table.rows;
  var propCells = rows[0].cells;
  var propNames = [];
  var results = [];
  var obj, row, cells;

  // Use the first row for the property names
  // Could use a header section but result is the same if
  // there is only one header row
  for (var i=0, iLen=propCells.length; i<iLen; i++) {
    propNames.push(propCells[i].textContent || propCells[i].innerText);
  }

  // Use the rows for data
  // Could use tbody rows here to exclude header & footer
  // but starting from 1 gives required result
  for (var j=1, jLen=rows.length; j<jLen; j++) {
    cells = rows[j].cells;
    obj = {};

    for (var k=0; k<iLen; k++) {
      obj[propNames[k]] = cells[k].textContent || cells[k].innerText;
    }
    results.push(obj)
  }
  return results;
}
于 2012-09-06T03:03:33.987 回答
1

尝试以下 n 列的方法

演示:http: //jsfiddle.net/ptVDm/7/

var tblhdr = $('table#students th').map(function () {
    return $(this).text();
}).get();

console.log(tblhdr);

var tbl = $('table#students tbody tr').map(function(idx, el) {
    var td = $(el).find('td');
    var obj = {id: idx+1};

    //Can work on number of columns
    for (var i = 0; i < tblhdr.length; i++) {
        obj[tblhdr[i]] = td.eq(i).text();
    }

    return obj;
}).get();

console.log(tbl);
于 2012-09-05T23:20:41.027 回答