如何用Handlebars访问嵌套对象值?JSReport数据渲染故障排查
问题分析与解决方案
你的核心问题是Java TreeMap序列化后,Handlebars无法读取到itemSalesSummary对象的属性,主要原因集中在Java对象序列化规则、Handlebars遍历逻辑两个层面,以下是具体修复步骤:
1. 先解决Java端序列化问题(最关键)
Java私有字段默认无法被JSON序列化工具(如Jackson)读取,必须为itemSalesSummary添加公开的getter方法,否则JSReport接收的JSON数据里不会包含productName、weekdayMapQty这些属性,Handlebars自然拿不到值。
修正后的Java类:
public class itemSalesSummary { private String productCode; private String productName; private Map<String, Integer> weekdayMapQty; // 必须添加以下getter方法 public String getProductCode() { return productCode; } public String getProductName() { return productName; } public Map<String, Integer> getWeekdayMapQty() { return weekdayMapQty; } }
同时确保productCodeMapSummary序列化后的JSON结构符合预期,应该是:
{ "123": { "productCode": "123", "productName": "product A", "weekdayMapQty": {"Mon":0, "Tue":0, ...} }, "456": {...}, "subtotal": {...} }
2. 修正Handlebars遍历代码
方案一:修复原有#each遍历逻辑
添加自定义helper保证星期列的顺序和表头一致,避免Map无序导致列错位:
{{#each productCodeMapSummary}} {{#xlsxAdd "xl/worksheets/sheet1.xml" "worksheet.sheetData[0].row"}} {{#if (isSubtotal @key)}} <row> <c t="str" ><v></v></c> <c t="str" ><v>{{@key}}</v></c> {{!-- 按固定顺序遍历星期,匹配表头列 --}} {{#each (getWeekdayValues this.weekdayMapQty)}} <c t="n" ><v>{{this}}</v></c> {{/each}} </row> {{else}} <row> <c t="str" ><v>{{@key}}</v></c> <c t="str" ><v>{{this.productName}}</v></c> {{#each (getWeekdayValues this.weekdayMapQty)}} <c t="n" ><v>{{this}}</v></c> {{/each}} </row> {{/if}} {{/xlsxAdd}} {{/each}} // 辅助函数:判断是否为汇总行 Handlebars.registerHelper("isSubtotal", function(key) { return key === "subtotal"; }); // 辅助函数:按固定顺序提取星期数值,保证列对应 Handlebars.registerHelper("getWeekdayValues", function(weekdayMap) { const order = ["Mon", "Tue", "Wed", "Thur", "Fri", "Sat", "Sun"]; return order.map(day => weekdayMap[day] || 0); });
方案二:修复自定义helper的参数错误
你之前的自定义helper参数数量不匹配,导致key变量未定义,修正后:
{{#each productCodeMapSummary}} {{#xlsxAdd "xl/worksheets/sheet1.xml" "worksheet.sheetData[0].row"}} <row> {{{printTableContent @key this}}} </row> {{/xlsxAdd}} {{/each}} Handlebars.registerHelper("printTableContent", function(key, value) { let content = ""; if(key === "subtotal"){ content = '<c t="str" ><v></v></c>' +'<c t="str" ><v>'+key+'</v></c>' }else{ content = '<c t="str" ><v>'+key+'</v></c>' +'<c t="str" ><v>'+ value.productName +'</v></c>' } // 补充星期列 const order = ["Mon", "Tue", "Wed", "Thur", "Fri", "Sat", "Sun"]; order.forEach(day => { content += `<c t="n" ><v>${value.weekdayMapQty[day] || 0}</v></c>`; }); return new Handlebars.SafeString(content); });
3. 关键注意点
- 确认Java端使用的JSON序列化工具(如Jackson)配置正确,没有忽略getter方法。
- 如果星期顺序仍有问题,Java端可以用
LinkedHashMap存储weekdayMapQty,保证遍历顺序固定。 - 避免使用三重花括号(
{{{}}})除非需要渲染HTML/XML标签,普通文本用双重花括号即可。
内容的提问来源于stack exchange,提问作者A.T.
相关产品推荐
相关产品推荐

