使用Java将yaml转为properties,保证顺序、实测无BUG版本

使用Java将yaml转为properties

    • [一、 前言](#一、 前言)
      • [1.1 顺序错乱的原因](#1.1 顺序错乱的原因)
      • [1.2 遗漏子节点的原因](#1.2 遗漏子节点的原因)
    • 二、优化措施
    • 三、源码

一、 前言

浏览了一圈网上的版本,大多存在以下问题:

  • 转换后顺序错乱
  • 遗漏子节点

基于此进行了优化,如果只是想直接转换,可直接使用我发布的 在线版本

如果想在工程中使用,可继续往下看,源码在文末。

1.1 顺序错乱的原因

大部分代码都是使用了java.util.Properties类来转换,这个类是基于ConcurrentHashMap来存储键值对的,必然会顺序错乱

这是截取的Properties类的部分源码:

java 复制代码
/**
  * Properties does not store values in its inherited Hashtable, but instead
  * in an internal ConcurrentHashMap.  Synchronization is omitted from
  * simple read operations.  Writes and bulk operations remain synchronized,
  * as in Hashtable.
  */
private transient volatile ConcurrentHashMap<Object, Object> map;

/**
     * Creates an empty property list with the specified defaults.
     *
     * @implNote The initial capacity of a {@code Properties} object created
     * with this constructor is unspecified.
     *
     * @param   defaults   the defaults.
     */
public Properties(Properties defaults) {
    this(defaults, 8);
}

private Properties(Properties defaults, int initialCapacity) {
    // use package-private constructor to
    // initialize unused fields with dummy values
    super((Void) null);
    map = new ConcurrentHashMap<>(initialCapacity);
    this.defaults = defaults;

    // Ensure writes can't be reordered
    UNSAFE.storeFence();
}

1.2 遗漏子节点的原因

主要还是代码不够严谨,解析的时候没有判断子节点是否是数组或对象,粗暴的转为String直接赋值了

二、优化措施

  • 基于LinkedHashMap来存储键值对

  • 递归遍历时判断子节点类型,不同类型采用不同的处理方式

三、源码

java 复制代码
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.yaml.snakeyaml.Yaml;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class YamlUtil {

    /**
     * yaml 转 Properties
     *
     * @param input
     * @return
     */
    public static String castToProperties(String input) {
        Map<String, Object> propertiesMap = new LinkedHashMap<>();
        Map<String, Object> yamlMap = new Yaml().load(input);
        flattenMap("", yamlMap, propertiesMap);
        StringBuffer strBuff = new StringBuffer();
        propertiesMap.forEach((key, value) -> strBuff.append(key)
                .append("=")
                .append(value)
                .append(StrUtil.LF));
        return strBuff.toString();
    }

    /**
     * 递归 Map 集合,转为 Properties集合
     *
     * @param prefix
     * @param yamlMap
     * @param treeMap
     */
    private static void flattenMap(String prefix, Map<String, Object> yamlMap, Map<String, Object> treeMap) {
        yamlMap.forEach((key, value) -> {
            String fullKey = prefix + key;
            if (value instanceof LinkedHashMap) {
                flattenMap(fullKey + ".", (LinkedHashMap) value, treeMap);
            } else if (value instanceof ArrayList) {
                List values = (ArrayList) value;
                for (int i = 0; i < values.size(); i++) {
                    String itemKey = String.format("%s[%d]", fullKey, i);
                    Object itemValue = values.get(i);
                    if (itemValue instanceof String) {
                        treeMap.put(itemKey, itemValue);
                    } else {
                        flattenMap(itemKey + ".", (LinkedHashMap) itemValue, treeMap);
                    }
                }
            } else {
                treeMap.put(fullKey, value.toString());
            }
        });
    }

}
相关推荐
S***267524 分钟前
基于SpringBoot和Leaflet的行政区划地图掩膜效果实战
java·spring boot·后端
马剑威(威哥爱编程)43 分钟前
鸿蒙6开发视频播放器的屏幕方向适配问题
java·音视频·harmonyos
JIngJaneIL1 小时前
社区互助|社区交易|基于springboot+vue的社区互助交易系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·社区互助
V***u4531 小时前
MS SQL Server partition by 函数实战二 编排考场人员
java·服务器·开发语言
这是程序猿2 小时前
基于java的ssm框架旅游在线平台
java·开发语言·spring boot·spring·旅游·旅游在线平台
i***t9192 小时前
基于SpringBoot和PostGIS的云南与缅甸的千里边境线实战
java·spring boot·spring
k***08292 小时前
【监控】spring actuator源码速读
java·spring boot·spring
麦麦鸡腿堡2 小时前
Java_网络编程_InetAddress类与Socket类
java·服务器·网络
vx_dmxq2112 小时前
【PHP考研互助系统】(免费领源码+演示录像)|可做计算机毕设Java、Python、PHP、小程序APP、C#、爬虫大数据、单片机、文案
java·spring boot·mysql·考研·微信小程序·小程序·php
5***g2983 小时前
新手如何快速搭建一个Springboot项目
java·spring boot·后端