Efficient JSON-Table Data Representation

First NameLast NamePoints
JillSmith50
EveJackson94
JohnDoe80
AdamJohnson67
JackLeay

<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