如何用SnakeYAML将点分隔键转为嵌套YAML对象?
问题描述
现有如下Java HashMap:
Map<String, Object> map = new HashMap<>(); map.put("a.b", "c"); map.put("a.d", "e");
使用SnakeYAML将其写入YAML文件的代码如下:
DumperOptions options = new DumperOptions(); options.setDefaultFlowStyle(FlowStyle.BLOCK); options.setPrettyFlow(true); Yaml yaml = new Yaml(options); String path = System.getProperty("user.dir") + "file.yaml"; try (FileWriter fileWriter = new FileWriter(path)) { yaml.dump(map, fileWriter); } catch (IOException e) { throw new RuntimeException(e); }
执行cat file.yaml后,文件内容为:
a.b: c a.d: e
但期望将点分隔的键转换为嵌套对象,输出如下格式:
a: b: c d: e
调整DumperOptions的setIndent()或FlowStyle参数无法解决问题,请问如何通过SnakeYAML实现需求?是否需要更换实现方式?
解决方案
SnakeYAML本身不会自动将点分隔的键映射为嵌套对象,核心是需要先将扁平结构的Map转换为嵌套结构的Map,再进行序列化,无需更换实现方式。
1. 实现扁平Map转嵌套Map的工具方法
编写工具方法,递归处理带点分隔的键,将其拆分为嵌套的Map结构:
public static Map<String, Object> flattenToNestedMap(Map<String, Object> flatMap) { Map<String, Object> nestedMap = new HashMap<>(); for (Map.Entry<String, Object> entry : flatMap.entrySet()) { String[] keys = entry.getKey().split("\\.", 2); if (keys.length == 1) { nestedMap.put(keys[0], entry.getValue()); } else { Map<String, Object> childMap = (Map<String, Object>) nestedMap.computeIfAbsent(keys[0], k -> new HashMap<>()); Map<String, Object> tempMap = new HashMap<>(); tempMap.put(keys[1], entry.getValue()); childMap.putAll(flattenToNestedMap(tempMap)); } } return nestedMap; }
2. 修改原代码,先转换再序列化
在dump之前,先调用上述方法将扁平Map转为嵌套结构:
DumperOptions options = new DumperOptions(); options.setDefaultFlowStyle(FlowStyle.BLOCK); options.setPrettyFlow(true); Yaml yaml = new Yaml(options); String path = System.getProperty("user.dir") + "file.yaml"; // 先转换为嵌套Map Map<String, Object> nestedMap = flattenToNestedMap(map); try (FileWriter fileWriter = new FileWriter(path)) { yaml.dump(nestedMap, fileWriter); } catch (IOException e) { throw new RuntimeException(e); }
3. 最终输出结果
执行后,file.yaml的内容将符合预期:
a: b: c d: e
内容的提问来源于stack exchange,提问作者Scott
相关产品推荐
相关产品推荐

