I need to write a large data-set to a web-page (using server-side-rendering) that will be consumed by JavaScript components running in the page. This data consists of an array of objects for a data-grid component and a charting component (so each array element is a data-grid row).
I'd like to use use JavaScript object constructors instead of object literals for performance reasons (there are JIT compiler optimizations for objects using constructors and they use less space on-the-wire because property names are omitted). I can also use Date
constructors natively too.
Here is how I'm doing it right now:
<script type="text/javascript">
function WeeklySalesRow( weekName, date, totalSales, profit, loss, turnover, deltaSalesPercentage, etc )
{
this.weekName = weekName;
this.date = date;
this.totalSales = totalSales;
this.profit = profit;
this.loss = loss;
// etc
}
var weeklySalesData = [
@{
Boolean first = true;
foreach( WeeklySalesRow row in this.Model.WeeklySalesData ) {
if( !first ) this.WriteLine( "," ); first = false;
this.Write( "new WeeklySalesRow( \"{0}\", new Date({1}), {2}, {3}, {4}, etc )", row.WeekName, row.Date.ToUnixTimestamp(), row.TotalSales, row.Profit, row.Loss, row.Turnover, etc );
}
}
];
function onDomContentLoaded( e ) {
var chartCompoennt = ...
chartComponent.loadData( weeklySalesData );
}
</script>
Renders like this:
// [...]
var weeklySalesData = [
new WeeklySalesRow( "2018W1", new Date(1514764800), 1100, 200, 900, 50, 0.56, etc ),
new WeeklySalesRow( "2018W2", new Date(1515369600), 1200, 100, 800, 45, 0.80, etc ),
new WeeklySalesRow( "2018W3", new Date(1515974400), 1300, 50, 700, 65, 0.12, etc ),
new WeeklySalesRow( "2018W4", new Date(1516752000), 1400, 25, 600, 80, 0.45, etc ),
new WeeklySalesRow( "2018W5", new Date(1517443200), 1500, 12, 500, 90, 0.123, etc ),
// etc...
];
// [...]
Which is more succinct than:
var weeklySalesData = [
{ weekName: "2018W1", date: "2018-01-01", totalSales: 1100, profit: 200, loss: 900, turnover: 50, deltaSalesPercentage: 0.56, etc },
{ weekName: "2018W2", date: "2018-01-08", totalSales: 1200, profit: 100, loss: 800, turnover: 50, deltaSalesPercentage: 0.56, etc },
{ weekName: "2018W3", date: "2018-01-17", totalSales: 1300, profit: 50, loss: 700, turnover: 50, deltaSalesPercentage: 0.56, etc },
{ weekName: "2018W4", date: "2018-01-23", totalSales: 1400, profit: 25, loss: 600, turnover: 50, deltaSalesPercentage: 0.56, etc },
{ weekName: "2018W5", date: "2018-02-01", totalSales: 1500, profit: 12, loss: 500, turnover: 50, deltaSalesPercentage: 0.56, etc },
];
I know that runtime components that have the ability to parse JSON directly (e.g. fetch
and XMLHttpRequest
) are able to mitigate certain performance harms that come from using object-literal notation (e.g. a the parser inspects the array and sees that all object-literals share the same set of property names and can therefore define an internal hidden base class for them within the runtime) - but that optimization doesn't apply in this case because the data is being rendered into the an SSR web-page and I understand even recent performance benchmarks don't show any parser or compiler optimizations for the "all array elements look-alike" scenario).
Is there a way for Json.NET to do this for me automatically, using reflection to automatically generate a JavaScript constructor and JavaScript constructor calls?