You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何用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

火山引擎 最新活动