如何用FreeMarker生成嵌套实体JSON?模板创建方法问询
使用FreeMarker生成带嵌套实体的JSON模板方案
没问题,我来帮你搞定这个FreeMarker模板的事儿!针对你给出的Field实体结构和期望的JSON输出,咱们一步步来构建对应的模板,还能支持多层嵌套的扩展场景。
第一步:调整实体类(必填)
你给出的Field类里List<Field> fields被注释了,首先得把它放开,因为嵌套结构需要这个属性来存储子字段:
@Data public class Field { private String name; private boolean isNested; private List<Field> fields; // 取消注释,用于存储嵌套字段 }
第二步:构造测试数据示例
对应你给出的测试结构,用Java代码构造数据的示例如下:
import java.util.Arrays; import java.util.List; // 构造嵌套字段 Field nameD = new Field("NameD", false, null); Field nameE = new Field("NameE", false, null); List<Field> nameCFields = Arrays.asList(nameD, nameE); // 构造根字段 Field nameA = new Field("NameA", false, null); Field nameB = new Field("NameB", false, null); Field nameC = new Field("NameC", true, nameCFields); List<Field> rootFields = Arrays.asList(nameA, nameB, nameC);
第三步:编写FreeMarker模板核心代码
因为嵌套结构可能有多层(不只是示例里的一层),咱们用递归宏来处理,这样扩展性更强。创建一个nested-json.ftl模板文件,内容如下:
<#-- 定义递归宏,用于渲染单个Field --> <#macro renderField field> "${field.name}": { <#-- 判断是否为嵌套字段,同时检查子字段列表是否存在且非空 --> <#if field.isNested && field.fields?? && field.fields?size > 0> "Nested": { <#list field.fields as nestedField> <@renderField field=nestedField /><#if nestedField_has_next>,</#if> </#list> } <#else> "Type": "NotNested" </#if> } </#macro> <#-- 根节点JSON结构 --> { <#list rootFields as field> <@renderField field=field /><#if field_has_next>,</#if> </#list> }
模板逻辑说明
- 递归宏
renderField:负责处理单个Field的渲染逻辑,不管是根字段还是嵌套子字段都能复用 - 空安全判断:用
field.fields??检查子字段列表是否存在,field.fields?size > 0确保有内容,避免空指针异常 - JSON格式兼容:键名用双引号包裹,符合标准JSON规范(如果你的需求是像示例那样不加引号,直接去掉模板里的双引号即可,但不推荐,因为不符合JSON语法)
- 逗号处理:用
field_has_next判断当前元素是否为列表最后一个,避免生成多余的逗号导致JSON格式错误
第四步:Java端渲染模板
把构造好的rootFields放入FreeMarker的数据模型,然后加载模板渲染即可,核心代码示例:
import freemarker.template.Configuration; import freemarker.template.Template; import java.io.StringWriter; import java.util.HashMap; import java.util.Map; // 初始化FreeMarker配置(建议全局单例) Configuration cfg = new Configuration(Configuration.VERSION_2_3_32); cfg.setClassForTemplateLoading(YourClass.class, "/templates"); // 模板文件所在路径 // 加载模板 Template template = cfg.getTemplate("nested-json.ftl"); // 构建数据模型 Map<String, Object> dataModel = new HashMap<>(); dataModel.put("rootFields", rootFields); // 渲染模板到字符串 StringWriter writer = new StringWriter(); template.process(dataModel, writer); String jsonOutput = writer.toString(); System.out.println(jsonOutput);
最终输出效果
运行后生成的JSON和你期望的格式一致(标准JSON格式,键名带双引号):
{ "NameA": { "Type": "NotNested" }, "NameB": { "Type": "NotNested" }, "NameC": { "Nested": { "NameD": { "Type": "NotNested" }, "NameE": { "Type": "NotNested" } } } }
内容的提问来源于stack exchange,提问作者niaomingjian




