I am trying to convert this HTML table:
Code:
See updated fiddle. The additional array map
is unnecessary because you are looking for a literal object for your JSON at this point.
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();
Try below approach for n columns
DEMO: 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);
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();
→
I needed this exact thing, except I needed more features to be able to override column names and ignore any hidden rows. I wrote a jQuery plugin that does just that, located here https://github.com/lightswitch05/table-to-json
for your example you would do: (http://jsfiddle.net/ptVDm/118/)
var table = $('#students').tableToJSON();
One thing to note is that the id's aren't part of the resulting object. You could just get the id from the object's array location. Or if you really needed it to be part of the object, you could create an hidden column for the ID's and then they would be included
The following should work:
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);
Basically, I find the object properties from the table head, next I create an object for each row, assigning values to property names as deduced from the earlier array.
Some obvious flaws:
colspan
attribute in the table, this system won't automatically replicate the same value in different object properties, but rather limit to setting up to the remaining <td>
s.Seeing Josiah's approach, it's probably faster than mine since mine tries to be smarter by finding property names. I would recommend his technique if you know for sure your table structure will not change. Otherwise, you would need something on the lines of my code.
Oh, and for the sake of completeness, here's a JSFiddle with mine.
Dunno if jQuery helps much in this case, here's a plain JS solution that is reasonably independent of the table structure. It just requires that the first row is a header (can be a different table section element or not) and the rows 1+ are data.
The table can have as many columns or rows as you like, if there are rowspan or colspans in there it will mess with the result (but jQuery won't help you with that either).
It could easily be adapted to specifically use the header section for the property names and to ignore a footer section:
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;
}