I can probably help here. I use it to construct my data reports into an email.
Javascript:
var model = {"crit": crit, "urgent": urgent, "warn":warn};
//print(JSON.stringify(model));
var template = com.serotonin.m2m2.Common.freemarkerConfiguration.getTemplate("datapoint_email.ftl");
var writer = new java.io.StringWriter();
template.process(model, writer);
var emailContent = new com.serotonin.web.mail.EmailContent(null, writer.toString(), com.serotonin.m2m2.Common.UTF8);
var recipients = ["fox@domain.com"];
com.serotonin.m2m2.rt.maint.work.EmailWorkItem.queueEmail(recipients, "Datapoint Summary", emailContent, null);
Template
<#assign key_list = crit?keys/> <!-- get keys -->
<#list key_list as c> <!-- c is your array index -->
<!-- markup fluff here -->
<#list crit[c] as k,x> <!-- this point here would be your tmpRecs object -->
<#assign row = row + 1/>
<#if row == 2><#assign row = 0/></#if>
<tr class="critrow<#if row == 1>Alt</#if>">
<td colspan="4">${x["id"]} </td>
<td colspan="4"><span style="font-weight:bold">${x["deviceName"]}</span><span> : ${x["pointName"]}</span></td>
<td colspan="4">${x["time"]} </td>
<td colspan="4">${x["value"]} </td>
</tr>
<#else>
<tr><td colspan="12">No Critical Items</td></tr>
</#list>
Would be good to see how you've laid out your model because that's what affects how the loop has to parse the data.
Fox