如何把数据导出为yaml文档

需求描述

需求:根据用户在web界面勾选的配置生成一份如下格式文档,保留注释。

yaml 复制代码
# 我是注释
VERSION: '1.0'

# 我是注释
FILE_NAME: foo

# 我是注释
UNWIND:
  COUNT: 3
  UNWIND_CHECK: true
  
# 我是注释
FLAGS:
  FLAG1: true
  FLAG2: false
  FLAG3: true
  FLAG4: true
  
 # 我是注释
 DEFINES:
  - DEFINE1
  - DEFINE2
  - DEFINE3

技术调研

这里直接给结论,关于下面提及的技术在网上资料很多,我也会把我参考的资料贴在文章尾部。

简单介绍一下这里提及的两个技术:

  • snakeyaml: 支持javabean转为yaml文件,也支持读取yaml文件为javabean对象。类似fastjson可以实现javabean与json相互转化。
  • freemark:比较成熟的template engine之一。
  1. 采用snakeyaml

    • 优点:生成yaml文件简单,有相应的api可直接调用。只要把封装数据传给snakeyaml即可
    • 缺点:
      • 和需求文档中的变量顺序不一致,生成的按照字母顺序排序;注释不好处理 。
      • java对象属性名需要和yaml中的一致。但是yaml中采用大写加下划线的风格、java中变量名采用驼峰命名风格。(初步尝试了做变量风格转换,要继承snakeyaml的一些类重写部分函数,比较复杂。而且后面要读取yaml文档时,又要做一次逆向风格替换。)
  2. 采用freemarker

    • 优点:
      • 以按照需求文档中的配置项顺序生成yaml文件
      • 变量名风格可以不一致
    • 缺点:
      • 需要自己写yaml语法规则
      • 如果变量名风格不一致,在读取yaml文件时会增加复杂度
  3. snakeyaml + freemarker

    • 优点:
      • 可以按照需求文档中的配置项顺序生成yaml文件
      • 生成yaml文件逻辑较为简单
    • 缺点:
      • 需求文档中使用块序列风格,这种方式将以流序列风格生成文档
      • 如果变量名风格不一致,在读取yaml文件时会增加复杂度

调研反馈

和产品沟通后,第三种方式提到的两个缺点不是问题。

结论:1.读取yaml文件功能不需要开发(是我多虑了,哈哈);2.块序列风格转为流序列风格。

理论落地

snakeyaml + freemarker的实现思路是:根据需求中的yaml文件提取出一个模板,然后通过数据填充的方式,给模板填充使用snakeyaml预处理过的数据,如此即可生成一份令产品满意的yaml文档。

step 1:提取freemark模板

ftl 复制代码
# 我是注释
VERSION: ${dumpHelper.settingBO.version!}

# 我是注释
FILE_NAME: ${dumpHelper.settingBO.fileName!}

# 我是注释
UNWIND: ${dumpHelper.getUnwind()!}

# 我是注释
FLAGS: ${dumpHelper.getFlags()!}

# 我是注释
DEFINES: ${dumpHelper.getDefines()!}

step 2: 编写生成yaml文件工具类

java 复制代码
public class YamlGeneratorUtil {
    private static final Configuration freemarkerConfig;

    static {
        // 初始化Freemarker配置
        freemarkerConfig = new Configuration(Configuration.VERSION_2_3_0);
        freemarkerConfig.setClassForTemplateLoading(YamlGeneratorUtil.class, "/templates/");
    }

    /**
     * 根据模板生成单个yaml配置文件
     * @param templateName 模板名称
     * @param outputFileName 生成的文件名
     * @param settingDumpHelper 配置转储辅助类
     */
    public static void generate(String templateName, String outputFileName, SettingDumpHelper settingDumpHelper) {
        try (FileWriter fileWriter = new FileWriter(outputFileName)) {
            Template template = freemarkerConfig.getTemplate(templateName);
            Map<String, Object> dataModel = new HashMap<>();
            dataModel.put("dumpHelper", freemarkerConfig.getObjectWrapper().wrap(settingDumpHelper));
            String config = FreeMarkerTemplateUtils.processTemplateIntoString(template, dataModel);
            fileWriter.write(config);
            System.out.println(config);
        } catch (IOException | TemplateException e) {
            throw new BusinessException(ErrorEnum.build(ErrorEnum.INTERNAL_SERVER_ERROR, "生成yaml文件失败:" + e.toString()));
        }
    }
}

step 3:编写SettingDumpHelper转储辅助类

由于业务特殊,源码就不贴了。这个类具体怎么写根据大家自己的业务逻辑,它的作用是利用snakeyaml对数据进行预处理,把数据转换成yaml的流序列格式。

java 复制代码
示例:
DumperOptions dumperOptions = new DumperOptions();
// 指定流序列格式
dumperOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.FLOW);
Yaml settingDumper = new Yaml(dumperOptions);
// 把数据转换成yaml的流序列格式。
public String getFlags() {
       return settingDumper.dump(settingBO.getFlags());
}

step 4:利用工具类生成yaml文件

java 复制代码
YamlGeneratorUtil.generate("config.ftl", your_output_file, your_dump_helper);

参考资料

相关推荐
云和数据.ChenGuang1 小时前
langchain4j InMemoryEmbeddingStore常用的方法
java·人工智能·windows·java-ee·fastapi·springai
小番茄程序猿2 小时前
RAG 的 precision 只有 0.55,我以为检索烂了,MRR 一测才发现是我用错了尺子
java·后端
天空鸟_时光不老2 小时前
07-检查点与状态持久化
java·人工智能·spring boot·spring·spring cloud·kafka·maven
GoodStudyAndDayDayUp2 小时前
一个简单的java jar跑docker
java·docker·jar
Nebula_g2 小时前
JavaSE加强:Commons-io框架
java·开发语言·算法·javase
程序猿_极客2 小时前
【免费】2026分享一套优质的基于Java的电子产品抢购管理系统的设计与实现(智能推荐算法+可视化图表),源码+文档+视频详解(讲解)
java·spring boot·后端·协同过滤·电子产品抢购系统
小羊没烦恼!2 小时前
关于大型asp.net应用系统的架构-架构的选择
java·服务器·开发语言·前端·c#
天空鸟_时光不老2 小时前
09-RAG问答系统落地:从默认分割器的坑到Milvus召回调优
java·人工智能·spring boot·spring·spring cloud·maven·mybatis
小羊没烦恼!2 小时前
Windows Azure Platform体验(1):Windows Azure
java·大数据·后端·python·flask·word·.net
suaizai_2 小时前
ComputerUse:让AI真正操控桌面系统
java·前端·javascript