Efficient JSON-Table Data Representation

Posted at




































First Name Last Name Points
Jill Smith 50
Eve Jackson 94
John Doe 80
Adam Johnson 67
Jack Leay





<table id="example_table_for_efficient_json_table_representation">
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Points</th>
</tr>
</thead>
<tbody>
<tr>
<td>Jill</td>
<td>Smith</td>
<td>50</td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
</tr>
<tr>
<td>John</td>
<td>Doe</td>
<td>80</td>
</tr>
<tr>
<td>Adam</td>
<td>Johnson</td>
<td>67</td>
</tr>
<tr>
<td>Jack</td>
<td>Leay</td>
<td></td>
</tr>
</tbody>
</table>





First Name	Last Name	Points
Jill	Smith	50
Eve	Jackson	94
John	Doe	80
Adam	Johnson	67
Jack	Leay	[missing?]

{
    headers: [   "First Name",  "Last Name", "Points"]
  , table:   [   "Jill",        "Smith",           50
               , "Eve",         "Jackson,          94
               , "John",        "Doe",             80
               , "Adam",        "Johnson",         67
               , "Jack",        "Leay",            null  ]
}





access the "row/col" by modulo the length of headers (requires post processing)

instead of classic wasteful JSON representation (no post processing required) of
[
  { "First Name":....
   ,"Last Name":...
   ,"Points":...
  }
 ,{ "First Name":....
  .....
  }
 ,...
]


considering the fact there is little to do with JSON without.. doing something with the data, if you're going to process the data anyway, you might add a little/minimal o(n/k) operation to "expand the data"...

extracting the data from a table is quite easy (assuming specific classic XHTML format for code clarity, naturally infinite complexity can be introduced to support formats variations...)




(function(table){
"use strict";

var
headers = Array.prototype.map.call(table.querySelector('thead').querySelectorAll('th'), function(item){
return item.innerText
});

console.log(
headers
);

}(
document.querySelector('#example_table_for_efficient_json_table_representation')
));





(will render ["First Name", "Last Name", "Points"])




extracting the table's body is quite similar:




(function(table){
"use strict";

NodeList.prototype.map = Array.prototype.map;

var
headers = table.querySelector('thead').querySelectorAll('th').map(function(item){
return item.innerText
})

, body = table.querySelector('tbody').querySelectorAll('tr').map(function(item){
/*just a row as string: "Jill Smith 50" */
//return item.innerText;

/*row CORRECT representation (but a bit overly complex) as array of arrays: [ ["Jill","Smith","50"],["Eve","Ja...],...] */
return item.querySelectorAll('td').map(function(item){
return item.innerText
});
})
;

console.log(
headers
, body
);

}(
document.querySelector('#example_table_for_efficient_json_table_representation')
));





this will render the following result:
icompile.eladkarako.com__efficient-json-table-data-representation__table_extract_2




in-order to flatten the array-of-array structure *efficiently*, will use a bit of JavaScript "join magic" and some Discrete mathematics (formal language theory) trick - by using a phrase that is not in our "ABC" language we can join - and later split without any data-compromise!

(function(table){
"use strict";

NodeList.prototype.map = Array.prototype.map;

var
SAP = "||I_WILL_NEVER_BE_AN_ACTUAL_VALUE_IN_TABLE||"

, headers = table.querySelector('thead').querySelectorAll('th').map(function(item){
return item.innerText
})

, body = table.querySelector('tbody').querySelectorAll('tr').map(function(item){
/*just a row as string: "Jill Smith 50" */
//return item.innerText;

/*row CORRECT representation (but a bit overly complex) as array of arrays: [ ["Jill","Smith","50"],["Eve","Ja...],...] */
return item.querySelectorAll('td').map(function(item){
return item.innerText
}).join(SAP)
})
;

console.log(
headers
, body
);

}(
document.querySelector('#example_table_for_efficient_json_table_representation')
));





icompile.eladkarako.com__efficient-json-table-data-representation__table_extract_3




easy enough, using join with the same phrase on last array structure, following by split will result a one-level array, in which the values can be accessed by index % headers.length...

(function(table){
"use strict";

NodeList.prototype.map = Array.prototype.map;

var
SAP = "||I_WILL_NEVER_BE_AN_ACTUAL_VALUE_IN_TABLE||"

,
headers = table.querySelector('thead').querySelectorAll('th').map(function(item){
return item.innerText
})

, body = table.querySelector('tbody').querySelectorAll('tr').map(function(item){
/*just a row as string: "Jill Smith 50" */
//return item.innerText;

/*row CORRECT representation (but a bit overly complex) as array of arrays: [ ["Jill","Smith","50"],["Eve","Ja...],...] */
return item.querySelectorAll('td').map(function(item){
return item.innerText
}).join(SAP)
}).join(SAP).split(SAP)
;


console.log(
headers
, body
);

}(
document.querySelector('#example_table_for_efficient_json_table_representation')
));





result...

["Jill", "Smith", "50", "Eve", "Jackson", "94", "John", "Doe", "80", "Adam", "Johnson", "67", "Jack", "Leay", ""]





cleaning up the code, trimming and using a *less ridiculous* SAP:

(function(table){
"use strict";

NodeList.prototype.map = Array.prototype.map;

var SAP = "||||"
, headers = table.querySelector('thead').querySelectorAll('th').map(function(item){ return item.innerText })
, body = table.querySelector('tbody').querySelectorAll('tr').map(function(item){ return item.querySelectorAll('td').map(function(item){ return item.innerText }).join(SAP) }).join(SAP).split(SAP)
;

return { "headers": headers
, "table": body }
}(
document.querySelector('#example_table_for_efficient_json_table_representation')
));





will render a nice little result JSON,
just remember how to read it (yes! modulus! BECAUSE MATH IS FUN!! *sign* geeks-of-the-world--unite!)

icompile.eladkarako.com__efficient-json-table-data-representation__table_extract_4