ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

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

2026/8/14 5:20:36 拓冰建站 浏览量
使用Java将yaml转为properties,保证顺序、实测无BUG版本

使用Java将yaml转为properties

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

一、 前言

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

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

基于此进行了优化,如果只是想直接转换,可直接使用我发布的 在线版本
在这里插入图片描述
如果想在工程中使用,可继续往下看,源码在文末。

1.1 顺序错乱的原因

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

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

/*** 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 valuessuper((Void) null);map = new ConcurrentHashMap<>(initialCapacity);this.defaults = defaults;// Ensure writes can't be reorderedUNSAFE.storeFence();
}

1.2 遗漏子节点的原因

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

二、优化措施

  • 基于LinkedHashMap来存储键值对

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

三、源码

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());}});}}