代码之家  ›  专栏  ›  技术社区  ›  pbuchheit

如何使用Freemarker模板输出JSON

  •  0
  • pbuchheit  · 技术社区  · 3 年前

    public class Order {    
        public String orderNumber;
        public Date processed;
        public Boolean release; 
        public List<OrderLine> lines;       
    }
    
    public class OrderLine {
        public String unit;
        public Integer quantity;
        public String itemNumber;
    }
    

    {"OrderNo": "1055249", "OrderDate": "202103251951", "Release": true, "OrderLines": [
    {"UnitOfMeasure": "EA", "Quantity": "1", "ItemNo": "764724473433"},
    {"UnitOfMeasure": "EA", "Quantity": "1", "ItemNo": "764724810979"}
    ]}
    

    请注意订单行列表。我可以很容易地为其他属性组合一个模板,但是我不知道如何处理重复的元素,比如订单行。内置的 指令打印出每个元素,但我需要一个逗号分隔的值列表。

    有人知道在freemarker中这样做而不必创建自定义指令的方法吗?如果没有,是否有另一个模板库更适合我的尝试?

    0 回复  |  直到 3 年前
        1
  •  1
  •   pcsutar    3 年前

    你可以用 inbuilt loop vars 生成以逗号分隔的订单行列表。请参考以下示例:

    Order.ftl

    <#import "OrderLine.ftl" as OrderLine>
    {
        "OrderNo": "${order.orderNumber}",
        "OrderDate": "${order.processed?datetime}",
        "Release": ${order.release?c},
        "OrderLines": [
            <@OrderLine.OrderLine order.lines/>
        ]
    }
    

    OrderLine.ftl

    <#macro OrderLine lines>
    <#list lines as line>
            {
                "unit": "${line.unit}",
                "quantity": "${line.quantity}",
                "itemNumber": "${line.itemNumber}"
            }<#if line?is_last == false>,</#if>
    </#list>
    </#macro>
    

    在上面 ftl 我用过 ?is_last comma (,) 在列表中的两个订单行对象之间。

    而且 <#if line?is_last == false>,</#if> 可以替换为 <#sep>,</#sep> . check sep directive

    import java.io.StringWriter;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import freemarker.template.Configuration;
    import freemarker.template.Template;
    
    public class FreemarkerService {
    
        private static final Configuration CONFIGURATION = new Configuration(Configuration.VERSION_2_3_0);
    
        public static void main(String args[]) throws Exception {
            OrderLine orderLine   = new OrderLine("EA", 1, "764724473433");
            OrderLine orderLine2  = new OrderLine("EA", 1, "764724810979");
            List<OrderLine> lines = new ArrayList<>();
            lines.add(orderLine);
            lines.add(orderLine2);
    
            Order order = new Order("1055249", new Date(), true, lines);
    
            Map<String, Object> input = new HashMap<>();
            input.put("order", order);
    
            String json = generateJsonByTemplate("Order.ftl", input);
    
            System.out.println(json);
        }
    
        public static String generateJsonByTemplate(String templateName, Map<String, Object> input) throws Exception
        {
            String sourceCode = null;
    
            try
            {
                Template template   = CONFIGURATION.getTemplate(templateName);
                StringWriter writer = new StringWriter();
    
                template.process(input, writer);
                sourceCode = writer.toString();
            }
            catch (Exception exception)
            {
                throw new Exception("Processing failed for template '" + templateName  + "' with error: " + exception.getMessage(), exception);
            }
    
            return sourceCode;
        }
    }
    

    输出:

    {
        "OrderNo": "1055249",
        "OrderDate": "Aug 7, 2021 11:43:34 AM",
        "Release": true,
        "OrderLines": [
            {
                "unit": "EA",
                "quantity": "1",
                "itemNumber": "764724473433"
            },
            {
                "unit": "EA",
                "quantity": "1",
                "itemNumber": "764724810979"
            }
        ]
    }